﻿#if CLIENT

using System;
using System.Collections.Generic;
using System.Linq;

namespace EntryEngine.UI
{
    [Flags]
    public enum EAnchor
    {
        Left = 1,
        Top = 2,
        Right = 4,
        Bottom = 8,
        Center = 16,
        Middle = 32,
    }
    public enum EPivot
    {
        TopLeft = 0x00,
        TopCenter = 0x01,
        TopRight = 0x02,
        MiddleLeft = 0x10,
        MiddleCenter = 0x11,
        MiddleRight = 0x12,
        BottomLeft = 0x20,
        BottomCenter = 0x21,
        BottomRight = 0x22,
    }
    public delegate void DUpdate<T>(T sender, Entry e) where T : UIElement;
    public delegate void DDraw<T>(T sender, GRAPHICS spriteBatch, Entry e) where T : UIElement;
    public delegate void DUpdateGlobal(UIElement sender, bool senderEventInvoke, Entry e);

    /// <summary>子类控件会默认采用父类样式，例如0x11会采用0x10的样式</summary>
    public enum EUIType
    {
        UIElement = 0,

        TextureBox = 0x10,
        AnimationBox = 0x11,

        Panel = 0x20,
        UIScene = 0x21,
        Selectable = 0x22,

        Button = 0x30,

        Label = 0x40,

        TextBox = 0x50,

        CheckBox = 0x60,
        TabPage = 0x61,

        DropDown = 0x70,

        //Slider = 0x80,
        ScrollBar = 0x80,
    }
    public class UIStyle
    {
        public static UIStyle Style;

        internal Dictionary<EUIType, List<Action<UIElement>>> styles = new Dictionary<EUIType, List<Action<UIElement>>>();
        /// <summary>添加某类UI控件的默认样式</summary>
        /// <param name="uiType">UI控件类型</param>
        /// <param name="setStyle">设置UI样式的方法，返回true则设置了样式（例如CheckBox的单选框和复选框就可能类型都是CheckBox但是样式不同）</param>
        public void AddStyle(EUIType uiType, Action<UIElement> setStyle)
        {
            List<Action<UIElement>> sets;
            if (!styles.TryGetValue(uiType, out sets))
            {
                sets = new List<Action<UIElement>>();
                styles.Add(uiType, sets);
            }
            sets.Add(setStyle);
        }
        public bool FitStyle(UIElement element)
        {
            int uiType = (int)element.UIType;
            int value = uiType & 15;

            List<Action<UIElement>> sets;
            for (int v = 0; v <= value; v++)
            {
                EUIType type = (EUIType)((uiType >> 4 << 4) | v);
                if (styles.TryGetValue(type, out sets))
                {
                    for (int i = 0; i < sets.Count; i++)
                    {
                        sets[i](element);
                    }
                }
            }

            return false;
        }

        public static COLOR DEFAULT_COLOR = new COLOR(220, 223, 230);
        public static COLOR MAIN_COLOR = new COLOR(17, 131, 238);
        public static COLOR ToLight(COLOR originColor)
        {
            return ToLight(originColor, 0.2f);
        }
        public static COLOR ToLight(COLOR originColor, float percent)
        {
            return new COLOR(_MATH.InByte(originColor.R + (255 - originColor.R) * percent), _MATH.InByte(originColor.G + (255 - originColor.G) * percent), _MATH.InByte(originColor.B + (255 - originColor.B) * percent), originColor.A);
        }
        public static COLOR ToDark(COLOR originColor)
        {
            return ToDark(originColor, 0.2f);
        }
        public static COLOR ToDark(COLOR originColor, float percent)
        {
            float b = 1 / (1 - percent);
            return new COLOR(
                _MATH.InByte(_MATH.Round((originColor.R - 255 * percent) * b)),
                _MATH.InByte(_MATH.Round((originColor.G - 255 * percent) * b)),
                _MATH.InByte(_MATH.Round((originColor.B - 255 * percent) * b)),
                originColor.A);
        }
        public static void StyleButtonPatchBorder(Button item, COLOR defaultColor, COLOR hoverColor, byte bold, COLOR defaultFontColor)
        {
            COLOR fontColorUnable = ToLight(defaultFontColor, 0.6f);
            COLOR colorUnable = ToLight(defaultFontColor, 0.2f);
            COLOR colorClick = ToDark(hoverColor, 0.2f);

            item.Width = 100;
            item.Height = 40;
            item.SourceNormal = PATCH.GetNinePatch(COLOR.TransparentWhite, defaultColor, bold);
            item.SourceHover = PATCH.GetNinePatch(COLOR.TransparentWhite, hoverColor, bold);
            item.SourceClick = PATCH.GetNinePatch(COLOR.TransparentWhite, colorClick, bold);
            item.UpdateBegin = (sender, e) =>
            {
                if (sender.FinalEventable)
                {
                    if (sender.IsClick && sender.IsHover)
                    {
                        item.UIText.FontColor = colorClick;
                    }
                    else
                    {
                        if (sender.IsHover)
                        {
                            item.UIText.FontColor = hoverColor;
                        }
                        else
                        {
                            item.UIText.FontColor = defaultFontColor;
                        }
                    }
                }
                else
                {
                    item.UIText.FontColor = fontColorUnable;
                }
            };
        }
        public static void StyleButtonPatchBody(Button item, COLOR defaultColor, COLOR hoverColor, byte bold, COLOR defaultFontColor)
        {
            StyleButtonPatchBorder(item, defaultColor, hoverColor, bold, defaultFontColor);
            COLOR colorBorder = ToLight(hoverColor, 0.6f);
            COLOR colorBody = ToLight(hoverColor, 0.9f);
            item.SourceHover = PATCH.GetNinePatch(colorBody, colorBorder, bold);
            //item.SourceClick = item.SourceHover;
            item.SourceClick = PATCH.GetNinePatch(ToDark(colorBody), ToDark(colorBorder), bold);
        }
        public static void StyleButtonPatchBody2(Button item, COLOR defaultColor, COLOR defaultFontColor)
        {
            COLOR colorHover = ToLight(defaultColor);
            COLOR colorClick = ToDark(defaultColor);
            COLOR colorUnable = ToLight(defaultColor, 0.5f);

            item.Width = 100;
            item.Height = 40;
            item.SourceNormal = TEXTURE.Pixel;
            item.SourceHover = item.SourceNormal;
            item.SourceClick = item.SourceNormal;

            item.UIText.FontColor = defaultFontColor;

            item.UpdateBegin = (sender, e) =>
            {
                if (sender.FinalEventable)
                {
                    if (sender.IsClick && sender.IsHover)
                    {
                        item.Color = colorClick;
                    }
                    else
                    {
                        if (sender.IsHover)
                        {
                            item.Color = colorHover;
                        }
                        else
                        {
                            item.Color = defaultColor;
                        }
                    }
                }
                else
                {
                    item.Color = colorUnable;
                }
            };
        }
        public static void StyleButtonPatchBody3(Button item, COLOR defaultColor, COLOR contrastFontColor, byte bold)
        {
            COLOR colorBorder = ToLight(defaultColor, 0.6f);
            COLOR colorBody = ToLight(defaultColor, 0.9f);

            COLOR colorHover = ToLight(defaultColor);
            COLOR colorClick = ToDark(defaultColor);
            COLOR colorUnable = ToLight(defaultColor, 0.5f);
            COLOR colorUnableHover = ToLight(contrastFontColor, 0.5f);

            item.Width = 100;
            item.Height = 40;
            item.SourceNormal = PATCH.GetNinePatch(colorBody, colorBorder, bold);
            item.SourceHover = PATCH.GetNinePatch(colorHover, COLOR.TransparentBlack, 0);
            item.SourceClick = PATCH.GetNinePatch(colorClick, COLOR.TransparentBlack, 0);

            item.UIText.FontColor = contrastFontColor;

            item.UpdateBegin = (sender, e) =>
            {
                if (sender.FinalEventable)
                {
                    if (sender.IsHover)
                    {
                        item.UIText.FontColor = contrastFontColor;
                    }
                    else
                    {
                        item.UIText.FontColor = defaultColor;
                    }
                }
                else
                {
                    if (sender.IsHover)
                    {
                        item.UIText.FontColor = colorUnableHover;
                    }
                    else
                    {
                        item.UIText.FontColor = colorUnable;
                    }
                }
            };
        }
        public static void StyleButtonLabel(Button item)
        {
            StyleButtonLabel(item, MAIN_COLOR);
        }
        public static void StyleButtonLabel(Button item, COLOR defaultColor)
        {
            COLOR colorHover = ToLight(defaultColor);
            COLOR colorClick = ToDark(defaultColor);
            COLOR colorUnable = ToLight(defaultColor, 0.5f);

            item.Width = 0;
            item.Height = 0;

            item.UpdateBegin = (sender, e) =>
            {
                if (sender.FinalEventable)
                {
                    if (sender.IsClick && sender.IsHover)
                    {
                        item.UIText.FontColor = colorClick;
                    }
                    else
                    {
                        if (sender.IsHover)
                        {
                            item.UIText.FontColor = colorHover;
                        }
                        else
                        {
                            item.UIText.FontColor = defaultColor;
                        }
                    }
                }
                else
                {
                    item.UIText.FontColor = colorUnable;
                }
            };
        }
        static TEXTURE CheckBox_Normal;
        static TEXTURE CheckBox_Checked;
        static TEXTURE RadioButton_Normal;
        static TEXTURE RadioButton_Checked;
        public static void StyleCheckBox(CheckBox item)
        {
            StyleCheckBox(item, DEFAULT_COLOR, MAIN_COLOR);
        }
        public static void StyleCheckBox(CheckBox item, COLOR defaultColor, COLOR checkedFontColor)
        {
            if (CheckBox_Normal == null)
            {
                string key = "*.png";
                foreach (var pipeline in Entry._ContentManager.ContentPipelines)
                {
                    if (pipeline.Processable(ref key) && pipeline is ContentPipelineBinary)
                    {
                        //byte[] bytes1 = _IO.ReadByte("icon/fangxingweixuanzhong.png");
                        //byte[] bytes2 = _IO.ReadByte("icon/fangxingxuanzhongfill.png");
                        //string s1 = BuildBytesString(bytes1);
                        //string s2 = BuildBytesString(bytes2);
                        RadioButton_Normal = (TEXTURE)((ContentPipelineBinary)pipeline).LoadFromBytes(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 64, 0, 0, 0, 64, 16, 6, 0, 0, 0, 250, 249, 173, 157, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 32, 99, 72, 82, 77, 0, 0, 122, 38, 0, 0, 128, 132, 0, 0, 250, 0, 0, 0, 128, 232, 0, 0, 117, 48, 0, 0, 234, 96, 0, 0, 58, 152, 0, 0, 23, 112, 156, 186, 81, 60, 0, 0, 0, 6, 98, 75, 71, 68, 0, 0, 0, 0, 0, 0, 249, 67, 187, 127, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 0, 72, 0, 0, 0, 72, 0, 70, 201, 107, 62, 0, 0, 7, 199, 73, 68, 65, 84, 120, 218, 237, 93, 201, 79, 21, 77, 16, 175, 6, 253, 162, 137, 178, 4, 99, 98, 112, 101, 81, 64, 61, 24, 189, 184, 196, 127, 65, 64, 5, 69, 52, 222, 52, 16, 111, 250, 39, 160, 32, 87, 2, 122, 214, 16, 212, 131, 43, 234, 77, 20, 18, 140, 130, 136, 26, 64, 1, 19, 53, 241, 98, 8, 143, 37, 113, 1, 186, 190, 67, 189, 122, 124, 195, 247, 102, 186, 7, 222, 235, 126, 131, 243, 187, 84, 102, 222, 48, 85, 245, 235, 234, 101, 122, 41, 0, 66, 132, 8, 17, 34, 68, 136, 16, 127, 35, 132, 109, 3, 18, 5, 148, 40, 81, 174, 95, 15, 2, 4, 136, 131, 7, 233, 110, 113, 49, 201, 162, 34, 146, 27, 55, 146, 204, 200, 112, 74, 198, 228, 164, 83, 126, 251, 70, 242, 227, 71, 146, 131, 131, 128, 128, 128, 93, 93, 34, 77, 164, 137, 180, 31, 63, 108, 251, 253, 215, 129, 10, 122, 247, 110, 146, 87, 175, 34, 34, 34, 190, 127, 79, 82, 74, 52, 2, 214, 243, 238, 29, 201, 134, 6, 178, 103, 215, 46, 219, 252, 44, 27, 16, 161, 43, 86, 144, 60, 115, 134, 228, 155, 55, 102, 10, 120, 169, 232, 237, 37, 123, 79, 159, 102, 63, 108, 243, 153, 242, 32, 226, 132, 32, 121, 246, 44, 201, 207, 159, 109, 23, 229, 146, 33, 81, 162, 28, 29, 141, 5, 68, 212, 79, 219, 124, 51, 172, 27, 194, 77, 58, 245, 221, 45, 45, 116, 151, 251, 112, 191, 152, 157, 165, 62, 186, 167, 135, 222, 247, 242, 37, 93, 15, 13, 209, 245, 200, 8, 61, 23, 137, 208, 253, 137, 137, 255, 48, 33, 64, 100, 102, 210, 69, 86, 22, 253, 94, 80, 64, 247, 139, 138, 232, 122, 255, 126, 186, 222, 187, 151, 158, 91, 108, 205, 238, 236, 164, 247, 213, 212, 208, 88, 226, 195, 7, 219, 229, 96, 28, 84, 19, 46, 92, 32, 249, 235, 151, 191, 106, 53, 51, 67, 242, 209, 35, 146, 149, 149, 20, 72, 107, 215, 38, 221, 110, 137, 18, 101, 70, 6, 233, 61, 121, 146, 100, 123, 59, 201, 217, 89, 127, 126, 176, 223, 181, 181, 182, 203, 35, 233, 32, 71, 87, 175, 38, 121, 231, 142, 63, 162, 126, 254, 36, 217, 212, 68, 5, 176, 101, 139, 109, 127, 226, 251, 183, 117, 43, 201, 230, 102, 167, 221, 186, 184, 117, 139, 121, 178, 237, 79, 130, 137, 201, 202, 34, 249, 226, 133, 63, 66, 30, 62, 100, 98, 109, 251, 177, 56, 191, 115, 115, 41, 96, 111, 223, 214, 118, 89, 162, 68, 217, 221, 77, 23, 57, 57, 182, 253, 88, 34, 1, 217, 217, 36, 223, 190, 213, 243, 126, 124, 156, 228, 209, 163, 182, 237, 79, 56, 31, 18, 37, 202, 227, 199, 201, 191, 72, 68, 47, 16, 250, 250, 184, 2, 217, 182, 95, 223, 209, 104, 19, 70, 178, 179, 211, 159, 163, 219, 182, 217, 182, 223, 12, 63, 121, 121, 254, 42, 6, 183, 156, 1, 232, 26, 200, 80, 141, 62, 94, 162, 68, 249, 236, 25, 15, 170, 108, 219, 109, 156, 39, 137, 18, 101, 102, 38, 145, 209, 209, 161, 23, 8, 109, 109, 182, 237, 118, 119, 8, 17, 231, 71, 245, 26, 5, 143, 136, 136, 171, 86, 217, 182, 219, 54, 152, 7, 127, 129, 80, 83, 99, 219, 238, 121, 7, 120, 106, 22, 17, 61, 63, 231, 184, 169, 255, 75, 107, 188, 10, 206, 22, 161, 191, 223, 59, 0, 248, 235, 98, 231, 78, 123, 6, 35, 226, 252, 204, 157, 42, 114, 121, 112, 183, 252, 251, 248, 165, 130, 120, 202, 207, 39, 169, 26, 44, 242, 24, 203, 194, 204, 34, 41, 230, 41, 91, 21, 150, 223, 168, 62, 217, 32, 222, 42, 42, 148, 212, 74, 148, 40, 171, 171, 205, 25, 198, 139, 52, 136, 168, 158, 171, 191, 123, 215, 54, 145, 65, 7, 241, 248, 224, 129, 119, 0, 240, 90, 131, 129, 69, 167, 216, 234, 156, 170, 143, 74, 209, 25, 187, 160, 129, 187, 78, 146, 170, 49, 150, 129, 150, 64, 111, 89, 182, 169, 201, 54, 113, 203, 13, 196, 107, 75, 139, 55, 239, 61, 61, 201, 51, 192, 49, 218, 119, 195, 204, 76, 170, 212, 124, 178, 227, 159, 127, 156, 125, 105, 107, 43, 201, 161, 33, 250, 125, 122, 58, 38, 249, 190, 227, 185, 138, 10, 126, 143, 117, 127, 28, 45, 129, 106, 209, 169, 164, 36, 73, 132, 242, 14, 28, 55, 180, 183, 167, 6, 81, 229, 229, 177, 190, 113, 169, 144, 40, 81, 142, 140, 208, 69, 89, 89, 106, 248, 247, 228, 137, 183, 189, 151, 47, 39, 73, 49, 111, 189, 114, 67, 101, 165, 29, 66, 210, 210, 244, 2, 52, 81, 104, 104, 96, 189, 118, 252, 173, 170, 242, 14, 128, 190, 190, 196, 41, 140, 110, 182, 140, 190, 221, 101, 207, 29, 55, 253, 230, 39, 120, 72, 111, 99, 163, 153, 130, 95, 136, 250, 122, 227, 254, 34, 226, 252, 234, 170, 91, 87, 32, 37, 241, 178, 110, 93, 130, 20, 150, 149, 121, 71, 92, 119, 183, 29, 34, 202, 203, 237, 20, 252, 66, 148, 150, 218, 241, 255, 213, 43, 111, 187, 142, 28, 81, 189, 71, 179, 9, 227, 237, 213, 113, 192, 91, 175, 76, 57, 206, 131, 50, 4, 4, 108, 108, 52, 165, 215, 27, 141, 141, 100, 215, 202, 149, 102, 245, 170, 42, 158, 71, 185, 69, 161, 25, 0, 188, 175, 62, 14, 120, 207, 157, 41, 8, 16, 32, 74, 75, 73, 230, 229, 25, 211, 235, 137, 130, 2, 146, 234, 26, 151, 88, 168, 120, 247, 40, 183, 40, 212, 1, 128, 128, 128, 155, 54, 185, 254, 238, 216, 108, 105, 10, 230, 155, 92, 37, 56, 48, 77, 1, 1, 1, 135, 135, 189, 31, 218, 188, 89, 245, 26, 117, 0, 8, 16, 32, 84, 131, 187, 241, 113, 99, 142, 3, 0, 192, 190, 125, 102, 245, 165, 170, 93, 145, 136, 235, 79, 8, 8, 168, 222, 36, 171, 217, 5, 172, 89, 227, 173, 104, 122, 218, 172, 227, 27, 54, 152, 213, 167, 139, 220, 92, 99, 170, 4, 8, 16, 83, 83, 222, 191, 39, 44, 0, 66, 232, 65, 74, 219, 22, 248, 133, 102, 0, 120, 212, 112, 1, 2, 132, 71, 11, 145, 20, 124, 255, 110, 86, 159, 6, 16, 16, 208, 160, 93, 170, 38, 30, 1, 1, 61, 90, 136, 40, 52, 7, 129, 124, 90, 214, 13, 217, 217, 198, 28, 7, 0, 128, 36, 46, 122, 44, 22, 2, 4, 8, 211, 118, 121, 240, 174, 234, 34, 162, 208, 28, 4, 126, 253, 234, 253, 80, 97, 161, 89, 199, 239, 223, 55, 171, 79, 3, 8, 8, 104, 208, 46, 1, 2, 132, 138, 247, 47, 95, 84, 175, 209, 236, 2, 248, 124, 188, 27, 118, 236, 48, 230, 56, 2, 2, 222, 187, 71, 114, 116, 212, 152, 94, 79, 240, 231, 152, 233, 192, 84, 241, 174, 42, 55, 237, 0, 24, 28, 116, 253, 137, 15, 77, 26, 2, 29, 166, 252, 243, 135, 106, 192, 165, 75, 166, 244, 186, 56, 143, 36, 47, 94, 36, 187, 102, 102, 204, 169, 6, 4, 60, 112, 192, 251, 33, 143, 114, 211, 214, 19, 136, 197, 32, 83, 171, 128, 11, 113, 229, 138, 113, 127, 17, 81, 189, 24, 52, 55, 151, 176, 197, 32, 167, 98, 206, 136, 225, 134, 19, 39, 236, 16, 146, 150, 70, 146, 151, 105, 147, 5, 174, 0, 245, 245, 172, 215, 184, 191, 209, 173, 95, 238, 38, 210, 142, 173, 36, 17, 237, 65, 176, 68, 137, 242, 241, 99, 211, 132, 196, 183, 179, 180, 148, 228, 240, 112, 98, 10, 254, 211, 39, 146, 166, 231, 250, 221, 252, 123, 250, 212, 219, 222, 186, 186, 196, 43, 142, 230, 192, 241, 86, 204, 231, 246, 237, 159, 230, 229, 213, 57, 146, 199, 142, 145, 93, 55, 111, 210, 245, 224, 32, 93, 79, 77, 57, 229, 192, 0, 201, 27, 55, 98, 127, 103, 101, 149, 47, 142, 63, 136, 104, 117, 75, 152, 211, 144, 222, 94, 111, 3, 154, 155, 109, 19, 182, 220, 64, 188, 94, 191, 238, 74, 185, 68, 137, 242, 245, 235, 228, 27, 226, 200, 117, 227, 6, 62, 186, 100, 191, 37, 8, 58, 136, 71, 62, 41, 244, 251, 183, 55, 239, 85, 85, 134, 12, 74, 79, 39, 233, 209, 199, 166, 200, 152, 32, 232, 32, 50, 57, 81, 134, 27, 207, 35, 35, 198, 179, 145, 233, 29, 16, 97, 84, 84, 216, 38, 50, 104, 32, 222, 56, 7, 145, 10, 6, 106, 126, 124, 3, 133, 112, 30, 247, 118, 195, 228, 36, 61, 183, 125, 187, 109, 98, 83, 29, 196, 83, 65, 1, 241, 54, 49, 225, 205, 43, 39, 142, 176, 152, 118, 206, 249, 117, 160, 202, 246, 213, 223, 207, 199, 160, 109, 19, 157, 106, 32, 126, 120, 130, 71, 181, 253, 158, 199, 88, 73, 28, 237, 47, 206, 129, 154, 26, 189, 38, 235, 249, 115, 146, 1, 72, 121, 98, 132, 55, 78, 169, 163, 145, 68, 75, 162, 68, 121, 238, 156, 109, 187, 21, 14, 113, 186, 51, 221, 64, 8, 80, 18, 164, 132, 242, 196, 73, 180, 116, 179, 167, 181, 182, 218, 182, 91, 211, 49, 31, 17, 141, 136, 243, 83, 204, 249, 249, 182, 237, 79, 58, 63, 18, 37, 202, 194, 66, 189, 166, 158, 193, 9, 56, 2, 148, 82, 135, 107, 182, 51, 11, 152, 10, 60, 232, 49, 127, 196, 204, 12, 31, 60, 170, 87, 13, 238, 112, 65, 74, 157, 0, 143, 153, 98, 129, 224, 104, 242, 117, 193, 223, 191, 193, 75, 45, 67, 118, 115, 58, 56, 78, 105, 171, 139, 142, 142, 192, 23, 124, 124, 66, 184, 107, 104, 107, 243, 71, 8, 127, 93, 92, 187, 150, 170, 1, 193, 118, 145, 228, 41, 91, 213, 204, 221, 66, 240, 177, 244, 0, 53, 245, 75, 35, 140, 191, 26, 252, 230, 212, 229, 197, 16, 62, 38, 125, 234, 20, 201, 228, 15, 38, 73, 79, 118, 182, 115, 89, 150, 87, 231, 252, 38, 139, 102, 191, 207, 159, 183, 85, 14, 246, 211, 197, 35, 226, 124, 186, 51, 94, 68, 58, 124, 120, 113, 111, 155, 155, 35, 201, 235, 225, 124, 118, 110, 104, 40, 182, 133, 76, 128, 0, 49, 54, 246, 191, 205, 174, 124, 0, 6, 1, 1, 115, 114, 232, 154, 7, 165, 197, 197, 206, 116, 241, 123, 246, 208, 253, 244, 116, 255, 14, 3, 2, 118, 116, 208, 123, 106, 107, 133, 16, 66, 136, 129, 1, 155, 101, 144, 18, 160, 64, 224, 153, 197, 234, 106, 103, 98, 134, 160, 131, 215, 76, 248, 92, 127, 234, 252, 195, 136, 148, 133, 243, 95, 198, 112, 83, 219, 211, 99, 187, 40, 149, 136, 46, 203, 58, 11, 124, 17, 45, 69, 136, 248, 32, 66, 75, 74, 56, 21, 138, 243, 51, 115, 110, 206, 76, 41, 243, 158, 59, 214, 91, 87, 199, 118, 217, 230, 199, 47, 150, 77, 83, 20, 219, 4, 41, 64, 128, 56, 116, 136, 238, 242, 241, 232, 29, 59, 98, 167, 156, 5, 8, 16, 60, 88, 140, 243, 111, 227, 16, 16, 48, 18, 161, 231, 226, 252, 219, 56, 0, 0, 232, 234, 162, 190, 123, 108, 204, 182, 223, 33, 66, 132, 8, 17, 34, 68, 136, 16, 139, 193, 191, 236, 245, 145, 187, 166, 198, 222, 196, 0, 0, 0, 37, 116, 69, 88, 116, 100, 97, 116, 101, 58, 99, 114, 101, 97, 116, 101, 0, 50, 48, 49, 57, 45, 48, 53, 45, 50, 51, 84, 49, 51, 58, 49, 48, 58, 48, 48, 43, 48, 56, 58, 48, 48, 51, 147, 206, 23, 0, 0, 0, 37, 116, 69, 88, 116, 100, 97, 116, 101, 58, 109, 111, 100, 105, 102, 121, 0, 50, 48, 49, 57, 45, 48, 53, 45, 50, 51, 84, 49, 51, 58, 49, 48, 58, 48, 48, 43, 48, 56, 58, 48, 48, 66, 206, 118, 171, 0, 0, 0, 73, 116, 69, 88, 116, 115, 118, 103, 58, 98, 97, 115, 101, 45, 117, 114, 105, 0, 102, 105, 108, 101, 58, 47, 47, 47, 104, 111, 109, 101, 47, 97, 100, 109, 105, 110, 47, 105, 99, 111, 110, 45, 102, 111, 110, 116, 47, 116, 109, 112, 47, 105, 99, 111, 110, 95, 119, 113, 57, 101, 118, 106, 111, 98, 119, 49, 47, 100, 97, 110, 120, 117, 97, 110, 46, 115, 118, 103, 85, 0, 92, 243, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 });
                        RadioButton_Checked = (TEXTURE)((ContentPipelineBinary)pipeline).LoadFromBytes(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 64, 0, 0, 0, 64, 16, 6, 0, 0, 0, 250, 249, 173, 157, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 32, 99, 72, 82, 77, 0, 0, 122, 38, 0, 0, 128, 132, 0, 0, 250, 0, 0, 0, 128, 232, 0, 0, 117, 48, 0, 0, 234, 96, 0, 0, 58, 152, 0, 0, 23, 112, 156, 186, 81, 60, 0, 0, 0, 6, 98, 75, 71, 68, 0, 0, 0, 0, 0, 0, 249, 67, 187, 127, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 0, 72, 0, 0, 0, 72, 0, 70, 201, 107, 62, 0, 0, 6, 109, 73, 68, 65, 84, 120, 218, 237, 157, 75, 72, 21, 81, 24, 199, 191, 207, 178, 50, 42, 140, 162, 69, 100, 144, 21, 154, 22, 61, 52, 8, 178, 180, 93, 171, 66, 8, 4, 179, 199, 42, 104, 17, 5, 149, 181, 106, 19, 69, 186, 41, 104, 211, 170, 69, 11, 233, 65, 105, 109, 108, 149, 104, 66, 11, 189, 22, 89, 217, 75, 161, 23, 45, 34, 232, 73, 98, 57, 95, 139, 191, 231, 218, 228, 149, 59, 115, 239, 204, 253, 198, 123, 207, 111, 243, 103, 134, 121, 124, 143, 115, 207, 156, 51, 231, 204, 185, 68, 22, 139, 197, 98, 177, 88, 114, 17, 214, 54, 32, 40, 196, 17, 71, 156, 69, 139, 136, 137, 137, 55, 111, 198, 222, 85, 171, 160, 165, 165, 208, 37, 75, 160, 243, 230, 185, 213, 240, 237, 155, 91, 223, 189, 131, 190, 120, 1, 29, 24, 32, 33, 33, 233, 238, 230, 60, 206, 227, 188, 79, 159, 180, 253, 206, 57, 144, 232, 53, 107, 160, 205, 205, 34, 34, 34, 253, 253, 80, 199, 145, 140, 96, 238, 243, 248, 49, 180, 169, 9, 246, 172, 94, 173, 29, 159, 172, 1, 1, 157, 62, 29, 186, 119, 47, 180, 175, 47, 51, 9, 78, 151, 88, 12, 246, 238, 217, 99, 252, 208, 142, 103, 228, 65, 224, 152, 161, 251, 247, 67, 135, 134, 180, 83, 153, 54, 142, 56, 226, 12, 14, 198, 11, 196, 152, 159, 218, 241, 142, 12, 241, 42, 93, 68, 68, 186, 187, 181, 243, 149, 25, 186, 186, 114, 254, 145, 129, 64, 28, 56, 0, 29, 30, 214, 78, 137, 14, 198, 239, 195, 135, 181, 243, 145, 161, 132, 23, 20, 64, 111, 220, 208, 14, 125, 52, 185, 118, 13, 90, 80, 160, 157, 175, 128, 19, 95, 88, 8, 237, 234, 210, 14, 113, 228, 113, 196, 17, 231, 193, 3, 108, 44, 88, 16, 118, 126, 66, 107, 140, 192, 129, 249, 243, 177, 213, 209, 1, 93, 187, 54, 108, 135, 178, 6, 33, 33, 121, 244, 8, 239, 53, 182, 109, 99, 102, 102, 254, 242, 37, 232, 219, 228, 5, 110, 183, 136, 140, 87, 97, 183, 111, 67, 109, 226, 125, 195, 196, 196, 235, 214, 161, 32, 180, 183, 35, 174, 179, 103, 7, 125, 155, 192, 11, 0, 184, 114, 5, 186, 101, 75, 152, 49, 202, 9, 152, 152, 120, 211, 38, 108, 92, 190, 28, 244, 229, 3, 43, 0, 40, 161, 135, 14, 97, 107, 215, 174, 204, 68, 39, 215, 168, 171, 67, 156, 15, 30, 12, 234, 138, 105, 183, 1, 76, 63, 30, 37, 181, 167, 7, 123, 103, 206, 212, 11, 82, 46, 48, 60, 12, 173, 172, 68, 219, 224, 233, 211, 84, 175, 148, 114, 13, 128, 146, 200, 140, 196, 95, 188, 136, 189, 54, 241, 153, 97, 214, 44, 232, 165, 75, 241, 60, 164, 72, 154, 143, 128, 125, 251, 160, 213, 213, 218, 33, 201, 77, 170, 170, 208, 72, 220, 189, 59, 213, 43, 248, 46, 57, 241, 193, 13, 38, 38, 126, 249, 18, 123, 151, 45, 211, 14, 69, 206, 34, 36, 36, 67, 67, 216, 40, 41, 193, 48, 245, 159, 63, 94, 79, 79, 177, 6, 168, 175, 135, 218, 196, 171, 195, 196, 196, 197, 197, 208, 186, 58, 255, 167, 251, 196, 12, 203, 226, 134, 235, 215, 107, 251, 111, 249, 151, 88, 12, 141, 194, 202, 74, 175, 103, 120, 174, 1, 220, 173, 253, 169, 146, 248, 145, 17, 232, 245, 235, 80, 83, 115, 153, 25, 66, 115, 230, 184, 213, 236, 55, 199, 153, 243, 204, 117, 162, 78, 69, 5, 26, 133, 101, 101, 129, 95, 218, 61, 3, 39, 194, 56, 226, 136, 115, 243, 38, 54, 138, 139, 211, 246, 91, 68, 68, 150, 47, 135, 222, 186, 165, 237, 158, 55, 255, 207, 158, 13, 190, 0, 136, 200, 248, 212, 171, 168, 49, 58, 10, 199, 143, 31, 15, 220, 241, 132, 113, 104, 108, 140, 223, 55, 106, 56, 226, 136, 243, 240, 97, 112, 14, 143, 77, 182, 28, 187, 122, 134, 230, 220, 249, 117, 248, 216, 177, 176, 19, 159, 184, 32, 156, 56, 161, 237, 254, 36, 65, 113, 16, 151, 133, 11, 3, 114, 180, 182, 86, 219, 165, 137, 62, 162, 170, 207, 116, 226, 19, 199, 167, 181, 85, 59, 28, 137, 217, 185, 51, 153, 253, 30, 27, 129, 33, 52, 42, 210, 98, 100, 4, 141, 209, 198, 70, 109, 75, 192, 209, 163, 113, 187, 34, 133, 153, 22, 63, 57, 30, 11, 64, 73, 137, 182, 43, 110, 218, 218, 208, 221, 25, 28, 212, 182, 4, 118, 152, 23, 49, 119, 238, 104, 219, 227, 198, 244, 106, 38, 39, 121, 1, 16, 18, 146, 162, 34, 109, 87, 220, 180, 181, 105, 91, 48, 53, 236, 90, 186, 52, 217, 17, 201, 11, 0, 19, 19, 255, 255, 5, 141, 34, 66, 66, 210, 219, 171, 109, 70, 98, 34, 100, 151, 144, 144, 204, 157, 155, 236, 48, 143, 143, 0, 243, 162, 36, 42, 124, 252, 168, 109, 193, 4, 132, 132, 228, 195, 7, 109, 51, 226, 48, 49, 113, 96, 5, 192, 226, 141, 188, 41, 23, 79, 143, 6, 255, 248, 161, 109, 168, 155, 197, 139, 181, 45, 152, 0, 19, 19, 71, 200, 46, 33, 33, 249, 254, 61, 217, 97, 30, 27, 129, 230, 107, 217, 8, 192, 196, 228, 99, 176, 35, 99, 8, 9, 73, 132, 236, 98, 98, 226, 32, 10, 0, 19, 19, 191, 125, 171, 237, 143, 155, 228, 47, 56, 50, 14, 19, 19, 71, 205, 174, 55, 111, 146, 29, 225, 241, 17, 96, 38, 126, 68, 133, 218, 90, 188, 9, 92, 177, 66, 219, 18, 188, 113, 51, 131, 78, 59, 118, 104, 219, 227, 198, 172, 107, 48, 57, 30, 11, 192, 179, 103, 218, 174, 184, 201, 207, 199, 47, 174, 185, 89, 203, 2, 36, 222, 204, 197, 59, 127, 30, 58, 99, 134, 118, 100, 220, 12, 12, 164, 239, 232, 148, 24, 12, 10, 127, 20, 112, 66, 92, 68, 68, 228, 228, 73, 109, 247, 19, 99, 70, 71, 3, 24, 12, 114, 59, 108, 86, 196, 136, 26, 102, 88, 54, 188, 177, 1, 92, 223, 172, 95, 96, 70, 1, 163, 58, 28, 220, 215, 231, 213, 47, 159, 253, 214, 246, 246, 176, 2, 156, 30, 166, 255, 221, 212, 132, 40, 180, 182, 6, 213, 70, 192, 117, 86, 174, 196, 86, 107, 43, 244, 220, 57, 247, 125, 35, 4, 19, 19, 123, 207, 147, 231, 57, 129, 241, 5, 13, 152, 152, 184, 191, 95, 219, 79, 111, 252, 254, 13, 53, 223, 40, 154, 119, 245, 177, 24, 186, 109, 239, 223, 255, 19, 9, 38, 46, 42, 194, 254, 138, 10, 119, 171, 222, 104, 126, 190, 182, 71, 222, 40, 47, 199, 32, 85, 242, 182, 155, 255, 73, 161, 34, 34, 18, 139, 97, 107, 195, 6, 109, 87, 45, 99, 140, 141, 145, 96, 90, 248, 198, 141, 94, 79, 243, 95, 133, 9, 9, 201, 133, 11, 218, 254, 90, 254, 131, 137, 137, 77, 111, 196, 207, 105, 62, 65, 13, 48, 109, 26, 182, 158, 63, 135, 234, 247, 199, 115, 22, 33, 33, 49, 243, 34, 74, 75, 67, 255, 48, 4, 207, 150, 209, 81, 220, 248, 244, 105, 109, 255, 115, 30, 38, 38, 62, 117, 202, 111, 226, 199, 79, 79, 17, 211, 45, 66, 65, 184, 119, 15, 134, 212, 212, 104, 199, 35, 183, 184, 127, 31, 90, 93, 141, 31, 166, 136, 223, 43, 4, 244, 121, 184, 233, 29, 152, 9, 17, 246, 43, 225, 112, 49, 159, 135, 87, 84, 120, 109, 237, 79, 70, 218, 253, 88, 84, 61, 79, 158, 96, 203, 76, 142, 180, 132, 134, 144, 144, 28, 57, 146, 110, 226, 195, 179, 79, 68, 198, 151, 59, 179, 4, 75, 75, 75, 208, 249, 10, 124, 149, 48, 24, 106, 22, 137, 186, 123, 23, 186, 117, 107, 184, 197, 46, 219, 233, 236, 132, 110, 223, 142, 95, 190, 121, 4, 164, 79, 200, 203, 196, 21, 22, 162, 202, 234, 232, 136, 175, 122, 101, 241, 134, 89, 38, 142, 136, 136, 106, 106, 240, 168, 253, 250, 53, 232, 219, 132, 246, 46, 59, 190, 174, 221, 216, 58, 119, 216, 219, 213, 21, 214, 253, 178, 11, 243, 139, 15, 47, 241, 25, 199, 60, 26, 160, 87, 175, 106, 63, 77, 163, 73, 75, 11, 212, 172, 1, 148, 197, 196, 255, 7, 64, 68, 68, 126, 254, 212, 14, 189, 14, 191, 126, 65, 115, 96, 177, 232, 73, 11, 130, 136, 136, 148, 151, 67, 59, 59, 181, 83, 18, 58, 142, 56, 226, 116, 116, 96, 35, 106, 223, 92, 42, 130, 128, 48, 35, 64, 13, 13, 208, 215, 175, 181, 243, 21, 12, 175, 94, 65, 235, 235, 141, 159, 218, 241, 142, 60, 238, 191, 140, 105, 104, 64, 224, 122, 123, 181, 83, 153, 20, 71, 28, 113, 122, 122, 220, 9, 55, 131, 103, 150, 180, 65, 64, 203, 202, 204, 82, 40, 102, 69, 12, 236, 207, 212, 20, 45, 51, 231, 206, 220, 247, 204, 25, 99, 151, 118, 124, 252, 146, 53, 85, 81, 124, 18, 36, 19, 19, 87, 85, 97, 175, 249, 60, 186, 164, 36, 254, 149, 51, 19, 19, 23, 22, 98, 127, 130, 191, 141, 19, 18, 18, 211, 125, 77, 240, 183, 113, 68, 68, 212, 221, 141, 110, 238, 231, 207, 218, 126, 91, 44, 22, 139, 197, 98, 177, 164, 194, 95, 255, 193, 19, 137, 111, 128, 54, 137, 0, 0, 0, 37, 116, 69, 88, 116, 100, 97, 116, 101, 58, 99, 114, 101, 97, 116, 101, 0, 50, 48, 49, 57, 45, 48, 53, 45, 50, 51, 84, 49, 51, 58, 49, 48, 58, 48, 48, 43, 48, 56, 58, 48, 48, 51, 147, 206, 23, 0, 0, 0, 37, 116, 69, 88, 116, 100, 97, 116, 101, 58, 109, 111, 100, 105, 102, 121, 0, 50, 48, 49, 57, 45, 48, 53, 45, 50, 51, 84, 49, 51, 58, 49, 48, 58, 48, 48, 43, 48, 56, 58, 48, 48, 66, 206, 118, 171, 0, 0, 0, 77, 116, 69, 88, 116, 115, 118, 103, 58, 98, 97, 115, 101, 45, 117, 114, 105, 0, 102, 105, 108, 101, 58, 47, 47, 47, 104, 111, 109, 101, 47, 97, 100, 109, 105, 110, 47, 105, 99, 111, 110, 45, 102, 111, 110, 116, 47, 116, 109, 112, 47, 105, 99, 111, 110, 95, 119, 113, 57, 101, 118, 106, 111, 98, 119, 49, 47, 100, 97, 110, 120, 117, 97, 110, 102, 105, 108, 108, 46, 115, 118, 103, 155, 146, 58, 65, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 });
                        CheckBox_Normal = (TEXTURE)((ContentPipelineBinary)pipeline).LoadFromBytes(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 64, 0, 0, 0, 64, 16, 6, 0, 0, 0, 250, 249, 173, 157, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 32, 99, 72, 82, 77, 0, 0, 122, 38, 0, 0, 128, 132, 0, 0, 250, 0, 0, 0, 128, 232, 0, 0, 117, 48, 0, 0, 234, 96, 0, 0, 58, 152, 0, 0, 23, 112, 156, 186, 81, 60, 0, 0, 0, 6, 98, 75, 71, 68, 0, 0, 0, 0, 0, 0, 249, 67, 187, 127, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 0, 72, 0, 0, 0, 72, 0, 70, 201, 107, 62, 0, 0, 2, 43, 73, 68, 65, 84, 120, 218, 237, 221, 49, 78, 235, 64, 16, 198, 241, 153, 232, 9, 10, 184, 1, 112, 3, 16, 80, 1, 71, 64, 130, 11, 208, 3, 119, 178, 40, 195, 17, 194, 21, 32, 77, 64, 2, 46, 128, 196, 5, 8, 20, 80, 120, 94, 49, 56, 213, 139, 95, 108, 18, 89, 225, 251, 255, 154, 209, 38, 214, 218, 94, 127, 94, 185, 218, 53, 3, 0, 0, 0, 160, 197, 127, 218, 65, 148, 81, 70, 185, 186, 154, 173, 203, 203, 172, 103, 103, 89, 183, 183, 205, 205, 205, 215, 214, 186, 190, 209, 165, 21, 22, 22, 31, 31, 217, 120, 122, 202, 218, 239, 103, 45, 10, 239, 121, 207, 123, 95, 95, 109, 187, 111, 29, 128, 136, 136, 136, 141, 141, 108, 13, 6, 89, 119, 119, 187, 30, 47, 25, 97, 97, 241, 240, 144, 47, 216, 201, 137, 187, 187, 251, 235, 107, 211, 110, 26, 7, 96, 242, 198, 187, 185, 249, 112, 152, 191, 242, 224, 59, 19, 22, 22, 247, 247, 217, 56, 60, 108, 58, 35, 244, 218, 157, 181, 154, 234, 121, 240, 157, 115, 115, 243, 253, 253, 172, 231, 231, 11, 63, 95, 78, 253, 195, 97, 212, 26, 12, 114, 166, 216, 220, 236, 122, 124, 150, 93, 53, 142, 89, 111, 110, 166, 14, 121, 25, 101, 148, 183, 183, 139, 191, 160, 136, 136, 24, 143, 235, 47, 132, 7, 63, 111, 57, 174, 91, 91, 245, 47, 222, 219, 91, 211, 126, 155, 127, 3, 124, 155, 218, 225, 183, 174, 7, 236, 183, 154, 247, 248, 183, 252, 6, 192, 111, 65, 0, 196, 17, 0, 113, 4, 64, 28, 1, 16, 71, 0, 196, 17, 0, 113, 4, 64, 28, 1, 16, 71, 0, 196, 17, 0, 113, 4, 64, 28, 1, 16, 71, 0, 196, 17, 0, 113, 4, 64, 28, 1, 16, 71, 0, 196, 17, 0, 113, 4, 64, 28, 1, 16, 71, 0, 196, 17, 0, 113, 4, 64, 28, 1, 16, 71, 0, 196, 17, 0, 113, 4, 64, 28, 1, 16, 71, 0, 196, 17, 0, 113, 4, 64, 28, 1, 16, 71, 0, 196, 17, 0, 113, 4, 64, 28, 1, 16, 71, 0, 196, 17, 0, 113, 45, 3, 240, 254, 62, 237, 31, 22, 138, 92, 140, 106, 161, 200, 250, 163, 198, 227, 166, 253, 54, 15, 64, 88, 88, 60, 63, 215, 31, 84, 20, 179, 93, 48, 254, 103, 50, 142, 110, 110, 94, 20, 245, 71, 87, 203, 201, 207, 238, 79, 227, 43, 114, 115, 243, 235, 235, 108, 28, 28, 252, 251, 255, 227, 227, 108, 188, 188, 212, 175, 107, 137, 249, 170, 246, 17, 152, 93, 251, 229, 226, 205, 204, 236, 238, 46, 31, 248, 222, 94, 215, 183, 174, 109, 52, 202, 153, 249, 232, 104, 225, 203, 197, 231, 9, 62, 63, 171, 141, 10, 38, 27, 23, 160, 3, 163, 81, 214, 211, 211, 182, 59, 135, 204, 105, 203, 152, 149, 149, 108, 93, 92, 100, 48, 170, 45, 99, 118, 118, 178, 174, 175, 119, 61, 84, 203, 173, 250, 232, 126, 124, 204, 218, 239, 231, 139, 119, 117, 245, 211, 45, 99, 0, 0, 0, 0, 168, 249, 11, 158, 191, 71, 200, 104, 30, 246, 84, 0, 0, 0, 37, 116, 69, 88, 116, 100, 97, 116, 101, 58, 99, 114, 101, 97, 116, 101, 0, 50, 48, 49, 57, 45, 48, 53, 45, 50, 51, 84, 49, 51, 58, 49, 48, 58, 48, 48, 43, 48, 56, 58, 48, 48, 51, 147, 206, 23, 0, 0, 0, 37, 116, 69, 88, 116, 100, 97, 116, 101, 58, 109, 111, 100, 105, 102, 121, 0, 50, 48, 49, 57, 45, 48, 53, 45, 50, 51, 84, 49, 51, 58, 49, 48, 58, 48, 48, 43, 48, 56, 58, 48, 48, 66, 206, 118, 171, 0, 0, 0, 86, 116, 69, 88, 116, 115, 118, 103, 58, 98, 97, 115, 101, 45, 117, 114, 105, 0, 102, 105, 108, 101, 58, 47, 47, 47, 104, 111, 109, 101, 47, 97, 100, 109, 105, 110, 47, 105, 99, 111, 110, 45, 102, 111, 110, 116, 47, 116, 109, 112, 47, 105, 99, 111, 110, 95, 119, 113, 57, 101, 118, 106, 111, 98, 119, 49, 47, 102, 97, 110, 103, 120, 105, 110, 103, 119, 101, 105, 120, 117, 97, 110, 122, 104, 111, 110, 103, 46, 115, 118, 103, 101, 1, 101, 36, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 });
                        CheckBox_Checked = (TEXTURE)((ContentPipelineBinary)pipeline).LoadFromBytes(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 64, 0, 0, 0, 64, 16, 6, 0, 0, 0, 250, 249, 173, 157, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 32, 99, 72, 82, 77, 0, 0, 122, 38, 0, 0, 128, 132, 0, 0, 250, 0, 0, 0, 128, 232, 0, 0, 117, 48, 0, 0, 234, 96, 0, 0, 58, 152, 0, 0, 23, 112, 156, 186, 81, 60, 0, 0, 0, 6, 98, 75, 71, 68, 0, 0, 0, 0, 0, 0, 249, 67, 187, 127, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 0, 72, 0, 0, 0, 72, 0, 70, 201, 107, 62, 0, 0, 4, 24, 73, 68, 65, 84, 120, 218, 237, 157, 205, 107, 19, 65, 24, 198, 103, 214, 166, 165, 68, 69, 11, 165, 20, 233, 63, 32, 138, 122, 179, 158, 122, 171, 7, 75, 17, 74, 4, 237, 213, 84, 189, 247, 92, 5, 21, 47, 22, 107, 181, 66, 245, 82, 73, 241, 16, 90, 26, 154, 92, 252, 160, 69, 69, 234, 193, 40, 180, 189, 244, 238, 65, 188, 105, 196, 47, 152, 215, 195, 147, 105, 77, 204, 199, 206, 54, 155, 49, 59, 239, 239, 242, 48, 155, 221, 157, 247, 221, 247, 217, 205, 146, 157, 236, 8, 193, 48, 12, 195, 48, 12, 195, 48, 140, 91, 200, 221, 238, 128, 20, 41, 82, 29, 29, 104, 141, 141, 65, 207, 159, 135, 30, 57, 34, 164, 144, 66, 198, 227, 182, 19, 109, 89, 72, 144, 160, 111, 223, 208, 216, 216, 128, 166, 82, 208, 217, 89, 233, 73, 79, 122, 191, 126, 5, 221, 125, 96, 3, 16, 17, 17, 29, 58, 132, 86, 46, 7, 61, 118, 204, 246, 241, 114, 6, 18, 36, 232, 195, 7, 156, 96, 103, 206, 72, 41, 165, 148, 31, 63, 154, 238, 198, 216, 0, 219, 103, 188, 20, 82, 200, 183, 111, 177, 148, 11, 111, 13, 18, 36, 232, 253, 123, 52, 78, 158, 52, 189, 34, 120, 193, 122, 213, 151, 122, 46, 188, 117, 164, 144, 66, 158, 56, 1, 189, 120, 209, 116, 115, 115, 3, 72, 33, 133, 188, 112, 193, 118, 222, 76, 25, 36, 72, 208, 232, 168, 233, 102, 230, 95, 1, 68, 68, 244, 245, 43, 90, 123, 247, 218, 206, 155, 249, 155, 66, 1, 247, 2, 251, 246, 249, 221, 34, 160, 1, 136, 108, 167, 202, 84, 70, 22, 241, 187, 126, 192, 123, 0, 38, 42, 176, 1, 28, 135, 13, 224, 56, 108, 0, 199, 97, 3, 56, 14, 27, 192, 113, 216, 0, 142, 195, 6, 112, 28, 54, 128, 227, 176, 1, 28, 135, 13, 224, 56, 108, 128, 80, 200, 102, 241, 116, 174, 175, 15, 237, 222, 94, 104, 38, 99, 59, 178, 114, 248, 97, 80, 67, 89, 90, 66, 225, 19, 9, 12, 204, 248, 253, 91, 127, 130, 129, 52, 221, 221, 120, 156, 254, 233, 19, 150, 250, 127, 104, 227, 23, 126, 24, 100, 133, 229, 101, 20, 254, 220, 185, 242, 194, 151, 226, 21, 143, 119, 227, 11, 31, 148, 54, 219, 1, 180, 54, 185, 28, 10, 63, 50, 82, 109, 40, 22, 174, 151, 186, 240, 119, 239, 218, 142, 184, 28, 190, 2, 4, 226, 233, 83, 104, 189, 194, 235, 51, 253, 193, 3, 104, 34, 97, 59, 242, 114, 216, 0, 126, 33, 65, 130, 158, 61, 67, 99, 120, 24, 223, 180, 63, 126, 252, 179, 90, 73, 225, 103, 102, 160, 201, 164, 237, 240, 171, 193, 6, 168, 135, 46, 188, 20, 82, 72, 191, 133, 191, 127, 31, 122, 233, 146, 237, 240, 235, 193, 6, 168, 201, 171, 87, 40, 252, 217, 179, 40, 252, 247, 239, 229, 107, 148, 22, 254, 222, 61, 232, 229, 203, 182, 35, 247, 203, 127, 106, 128, 173, 45, 232, 192, 0, 244, 240, 97, 156, 137, 233, 116, 115, 250, 95, 89, 129, 158, 62, 141, 194, 235, 127, 230, 236, 80, 249, 140, 191, 114, 197, 226, 65, 107, 14, 20, 54, 138, 20, 169, 193, 193, 202, 253, 122, 30, 244, 241, 227, 112, 58, 95, 93, 133, 86, 255, 43, 155, 46, 60, 116, 122, 58, 244, 227, 97, 72, 235, 27, 128, 136, 136, 78, 157, 170, 221, 255, 158, 61, 208, 39, 79, 26, 211, 223, 203, 151, 48, 94, 245, 97, 238, 88, 79, 23, 126, 106, 170, 57, 199, 193, 156, 214, 55, 128, 34, 69, 234, 249, 115, 104, 123, 123, 213, 56, 20, 41, 82, 109, 109, 208, 133, 133, 96, 157, 189, 126, 141, 237, 235, 143, 163, 199, 122, 147, 147, 77, 174, 167, 49, 173, 111, 128, 18, 22, 23, 113, 224, 99, 177, 218, 133, 137, 197, 176, 126, 38, 227, 111, 191, 111, 222, 96, 187, 253, 251, 253, 21, 254, 230, 205, 230, 230, 29, 156, 136, 25, 64, 147, 78, 235, 51, 190, 118, 161, 218, 219, 177, 126, 54, 91, 121, 63, 239, 222, 65, 15, 30, 244, 151, 231, 141, 27, 118, 242, 13, 78, 68, 13, 160, 153, 155, 131, 122, 94, 237, 248, 58, 59, 97, 136, 23, 47, 160, 249, 60, 150, 119, 117, 249, 203, 239, 250, 117, 187, 121, 6, 39, 226, 6, 160, 226, 61, 194, 195, 135, 104, 84, 127, 168, 130, 207, 227, 113, 232, 129, 3, 81, 47, 188, 38, 250, 6, 208, 248, 52, 130, 191, 124, 174, 93, 179, 157, 78, 163, 112, 199, 0, 37, 220, 185, 19, 44, 143, 137, 9, 219, 145, 55, 26, 71, 13, 64, 197, 43, 194, 237, 219, 117, 227, 87, 164, 72, 141, 143, 219, 14, 55, 44, 220, 53, 64, 9, 183, 110, 109, 255, 78, 64, 68, 59, 191, 32, 94, 189, 106, 59, 178, 176, 49, 173, 103, 196, 135, 132, 125, 254, 12, 85, 10, 218, 211, 99, 59, 162, 176, 49, 29, 18, 22, 113, 3, 184, 7, 143, 9, 100, 140, 96, 3, 56, 14, 27, 192, 113, 216, 0, 142, 195, 6, 112, 28, 54, 128, 227, 4, 52, 64, 161, 96, 59, 112, 166, 18, 95, 190, 152, 110, 97, 110, 0, 18, 36, 104, 115, 211, 118, 170, 76, 37, 204, 235, 18, 240, 93, 193, 243, 243, 182, 83, 101, 42, 161, 231, 17, 240, 79, 240, 215, 197, 11, 33, 132, 88, 91, 131, 33, 142, 31, 183, 157, 186, 219, 228, 243, 184, 50, 247, 247, 135, 254, 186, 120, 116, 240, 243, 167, 158, 168, 96, 123, 226, 2, 198, 2, 249, 60, 116, 104, 40, 232, 204, 33, 13, 154, 50, 70, 143, 222, 77, 38, 97, 12, 61, 101, 204, 209, 163, 80, 126, 171, 248, 238, 208, 55, 221, 235, 235, 208, 84, 10, 39, 222, 163, 71, 187, 157, 50, 134, 97, 24, 134, 97, 24, 134, 97, 24, 215, 248, 3, 165, 16, 163, 27, 241, 201, 62, 149, 0, 0, 0, 37, 116, 69, 88, 116, 100, 97, 116, 101, 58, 99, 114, 101, 97, 116, 101, 0, 50, 48, 49, 57, 45, 48, 53, 45, 50, 51, 84, 49, 51, 58, 49, 48, 58, 48, 48, 43, 48, 56, 58, 48, 48, 51, 147, 206, 23, 0, 0, 0, 37, 116, 69, 88, 116, 100, 97, 116, 101, 58, 109, 111, 100, 105, 102, 121, 0, 50, 48, 49, 57, 45, 48, 53, 45, 50, 51, 84, 49, 51, 58, 49, 48, 58, 48, 48, 43, 48, 56, 58, 48, 48, 66, 206, 118, 171, 0, 0, 0, 87, 116, 69, 88, 116, 115, 118, 103, 58, 98, 97, 115, 101, 45, 117, 114, 105, 0, 102, 105, 108, 101, 58, 47, 47, 47, 104, 111, 109, 101, 47, 97, 100, 109, 105, 110, 47, 105, 99, 111, 110, 45, 102, 111, 110, 116, 47, 116, 109, 112, 47, 105, 99, 111, 110, 95, 119, 113, 57, 101, 118, 106, 111, 98, 119, 49, 47, 102, 97, 110, 103, 120, 105, 110, 103, 120, 117, 97, 110, 122, 104, 111, 110, 103, 102, 105, 108, 108, 46, 115, 118, 103, 56, 44, 126, 56, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 });
                    }
                }
            }

            if (item.IsRadioButton)
            {
                item.SourceNormal = RadioButton_Normal;
                item.SourceClicked = RadioButton_Checked;
            }
            else
            {
                item.SourceNormal = CheckBox_Normal;
                item.SourceClicked = CheckBox_Checked;
            }
            item.Width = 24;
            item.Height = 24;
            item.CheckedOverlayNormal = ECheckedOverlay.选中覆盖普通;

            COLOR colorUnable = ToLight(defaultColor, 0.6f);
            COLOR colorUnableChecked = ToLight(checkedFontColor, 0.6f);

            bool fontColorAuto = item.UIText.FontColor == COLOR.White;

            item.UpdateBegin = (sender, e) =>
            {
                if (sender.FinalEventable)
                {
                    if (sender.IsHover || item.Checked)
                    {
                        item.Color = checkedFontColor;
                    }
                    else
                    {
                        item.Color = defaultColor;
                    }
                }
                else
                {
                    if (sender.IsHover || item.Checked)
                    {
                        item.Color = colorUnableChecked;
                    }
                    else
                    {
                        item.Color = colorUnable;
                    }
                }
                if (fontColorAuto)
                    item.UIText.FontColor = item.Color;
            };
        }
        public static void StyleTextBox(TextBox item)
        {
            StyleTextBox(item, DEFAULT_COLOR, MAIN_COLOR, 1);
        }
        public static void StyleTextBox(TextBox item, COLOR defaultColor, COLOR inputColor, byte bold)
        {
            COLOR colorUnable = ToLight(defaultColor, 0.2f);
            COLOR colorHover = ToDark(defaultColor, 0.2f);

            item.Width = 200;
            item.Height = 40;
            item.DefaultText.TextAlignment = EPivot.MiddleLeft;
            item.DefaultText.Padding.X = 30;
            item.DefaultText.FontColor = defaultColor;
            item.UIText.TextAlignment = item.DefaultText.TextAlignment;
            item.UIText.Padding.X = item.DefaultText.Padding.X;
            item.SourceNormal = PATCH.GetNinePatch(COLOR.TransparentWhite, defaultColor, bold);
            item.SourceHover = PATCH.GetNinePatch(COLOR.TransparentWhite, colorHover, bold);
            item.SourceClicked = PATCH.GetNinePatch(COLOR.TransparentWhite, inputColor, bold);
        }

        /// <summary>按钮效果，点击时放大（使用了DrawAfterBegin和DrawBeforeEnd）</summary>
        /// <param name="scale">点击下去缩放的大小，放大推荐1.2，缩小推荐0.8</param>
        public static void EffectScale(UIElement element, float scale)
        {
            element.DrawAfterBegin += (sender, sb, e) =>
            {
                if (sender.IsHover && sender.IsClick)
                {
                    var pivot = sender.FinalViewClip.Center;
                    sb.Begin(MATRIX2x3.CreateTransform(0, pivot.X, pivot.Y, scale, scale, pivot.X, pivot.Y));
                }
            };
            element.DrawBeforeEnd += beqEnd;
        }
        static void beqEnd(UIElement sender, GRAPHICS sb, Entry e)
        {
            if (sender.IsHover && sender.IsClick)
            {
                sb.End();
            }
        }
        /// <summary>从左往右扫光特效</summary>
        /// <param name="light">扫光图片</param>
        /// <param name="target">需要扫光的控件</param>
        /// <param name="duration">扫光一遍需要的时间</param>
        /// <param name="interval">扫光后距离下次扫光间隔的时间</param>
        public static void EffectScan(TEXTURE light, UIElement target, float duration, float interval)
        {
            float x = -light.Width;
            float time = 0;
            target.DrawAfterEnd += (sender, spriteBatch, e) =>
            {
                if (x > target.Width + light.Width)
                {
                    time += e.GameTime.ElapsedSecond;
                    if (time >= interval)
                    {
                        x = -light.Width;
                        time = 0;
                    }
                    else
                    {
                        return;
                    }
                }
                x += target.Width * duration * e.GameTime.ElapsedSecond;
                var clip = target.ViewClip;
                var previous = spriteBatch.CurrentGraphics;
                RECT.Intersect(ref previous, ref clip, out clip);
                spriteBatch.Begin(clip);
                spriteBatch.Draw(light, new VECTOR2(clip.X + x, clip.Y));
                spriteBatch.End();
            };
        }
    }
    /// <summary>UI动态特效，淡入，淡出，从各个方向移出等</summary>
    public class UIEffect : ICoroutine
    {
        public UIEffect(UIElement element) { this.UI = element; }

        CorParallel coroutine = new CorParallel();
        ShaderAlpha alpha = new ShaderAlpha();
        public UIElement UI { get; private set; }
        /// <summary>不透明度，0~1，默认为1，1为不透明</summary>
        public float Alpha = 1;
        /// <summary>旋转角度</summary>
        public float Rotation;
        /// <summary>坐标偏移，是相对于UI原始坐标的偏移</summary>
        public VECTOR2 Offset;
        /// <summary>大小缩放，默认为1</summary>
        public float Scale = 1;

        public UIEffect Reset()
        {
            coroutine.Clear();
            Alpha = 1;
            Rotation = 0;
            Offset.X = 0;
            Offset.Y = 0;
            Scale = 1;
            return this;
        }
        /// <summary>用seconds秒钟从origin缩放到target</summary>
        public UIEffect DoScale(float origin, float target, float seconds)
        {
            Scale = origin;
            DoAnimation(_DoScale(origin, target, seconds));
            return this;
        }
        private IEnumerable<ICoroutine> _DoScale(float origin, float target, float seconds)
        {
            float elapsed = 0;
            while (elapsed < seconds)
            {
                elapsed += GameTime.Time.ElapsedSecond;
                if (elapsed > seconds)
                    Scale = target;
                else
                    Scale = origin + (target - origin) * (elapsed / seconds);
                yield return null;
            }
        }
        /// <summary>用seconds秒钟从origin透明渐变到target</summary>
        public UIEffect DoFade(float origin, float target, float seconds)
        {
            Alpha = origin;
            DoAnimation(_DoFade(origin, target, seconds));
            return this;
        }
        /// <summary>用seconds秒钟从透明变为不透明</summary>
        public UIEffect DoFadeIn(float seconds)
        {
            return DoFade(0, 1, seconds);
        }
        /// <summary>用seconds秒钟从不透明变为透明</summary>
        public UIEffect DoFadeOut(float seconds)
        {
            return DoFade(1, 0, seconds);
        }
        private IEnumerable<ICoroutine> _DoFade(float origin, float target, float seconds)
        {
            float elapsed = 0;
            while (elapsed < seconds)
            {
                elapsed += GameTime.Time.ElapsedSecond;
                if (elapsed > seconds)
                    Alpha = target;
                else
                    Alpha = origin + (target - origin) * (elapsed / seconds);
                yield return null;
            }
        }
        /// <summary>用seconds秒钟从origin旋转到target</summary>
        public UIEffect DoRotate(float origin, float target, float seconds)
        {
            Rotation = origin;
            DoAnimation(_DoRotate(origin, target, seconds));
            return this;
        }
        private IEnumerable<ICoroutine> _DoRotate(float origin, float target, float seconds)
        {
            float elapsed = 0;
            while (elapsed < seconds)
            {
                elapsed += GameTime.Time.ElapsedSecond;
                if (elapsed > seconds)
                    Rotation = target;
                else
                    Rotation = origin + (target - origin) * (elapsed / seconds);
                yield return null;
            }
        }
        /// <summary>用seconds秒钟从origin匀速平移到target</summary>
        public UIEffect DoMove(VECTOR2 origin, VECTOR2 target, float seconds)
        {
            Offset = origin;
            DoAnimation(_DoMove(origin, target, seconds));
            return this;
        }
        public UIEffect DoMoveX(float origin, float target, float seconds)
        {
            return DoMove(new VECTOR2(origin, 0), new VECTOR2(target, 0), seconds);
        }
        public UIEffect DoMoveY(float origin, float target, float seconds)
        {
            return DoMove(new VECTOR2(0, origin), new VECTOR2(0, target), seconds);
        }
        /// <summary>自动从贴近屏幕的位置移入到当前位置</summary>
        public UIEffect DoMoveAuto(float seconds)
        {
            var graphics = Entry.Instance.GRAPHICS.GraphicsSize;
            float x = UI.X;
            float ox = 0;
            if (x > graphics.X * 0.5f)
            {
                x = graphics.X - x;
                ox = graphics.X;
            }
            float y = UI.Y;
            float oy = 0;
            if (y > graphics.Y * 0.5f)
            {
                y = graphics.Y - y;
                oy = y;
            }
            if (x > y)
                return DoMoveY(oy, 0, seconds);
            else
                return DoMoveX(ox, 0, seconds);
        }
        private IEnumerable<ICoroutine> _DoMove(VECTOR2 origin, VECTOR2 target, float seconds)
        {
            float elapsed = 0;
            while (elapsed < seconds)
            {
                elapsed += GameTime.Time.ElapsedSecond;
                if (elapsed > seconds)
                {
                    Offset.X = target.X;
                    Offset.Y = target.Y;
                }
                else
                {
                    float percent = (elapsed / seconds);
                    Offset.X = origin.X + (target.X - origin.X) * percent;
                    Offset.Y = origin.Y + (target.Y - origin.Y) * percent;
                }
                yield return null;
            }
        }
        /// <summary>用seconds秒钟从origin缩放到target</summary>
        public UIEffect DoAnimation(IEnumerable<ICoroutine> coroutine)
        {
            this.coroutine.Add(coroutine);
            return this;
        }

        internal void Begin(GRAPHICS sb)
        {
            SHADER shader = null;
            if (Alpha < 1)
            {
                alpha.Alpha = Alpha;
                shader = alpha;
            }

            var viewclip = UI.ViewClip;
            float x = viewclip.X + UI.PivotAlignmentX * viewclip.Width * 0.5f;
            float y = viewclip.Y + UI.PivotAlignmentY * viewclip.Height * 0.5f;
            sb.Begin(
                //sb.FromPrevious(MATRIX2x3.CreateTransform(_MATH.D2R * Rotation, x, y, Scale, Scale, x + Offset.X, y + Offset.Y)),
                MATRIX2x3.CreateTransform(_MATH.D2R * Rotation, x, y, Scale, Scale, x + Offset.X, y + Offset.Y),
                sb.CurrentGraphics,
                shader);
        }

        public bool IsEnd
        {
            get { return coroutine.IsEnd; }
        }
        public void Update(float elapsed)
        {
            coroutine.Update(elapsed);
        }
    }

    public struct UIFlowLayout
    {
        public float MaginLeft;
        public float MaginTop;
        public float MaginRight;
        public float MaginBottom;
        /// <summary>占满一行</summary>
        public bool Line;
        internal float Y;
        internal float Bottom;
    }
    /// <summary>
    /// 简单，高性能绘制
    /// 1. 不用支持旋转、镜像
    /// 2. 非特殊情况下，不使用Transform、Shader和Scissor
    /// 
    /// 4种状态的Rectangle
    /// 1. 相对于 父容器 / 屏幕
    /// 2. 完整 / 裁剪
    /// 
    /// 更新顺序，绘制顺序，绘制覆盖顺序为逆序，所以可能需要将更新改为逆序
    /// 
    /// 每帧动作顺序
    /// 1. Childs从后往前Event, Parent.Event
    /// 2. Parent.Update, Childs从后往前Update
    /// 3. Parent.Draw, Childs从前往后Draw
    /// 
    /// IsClip及其相关参数的有不明确的地方，需要修改
    /// </summary>
    [Code(ECode.ToBeContinue)]
    public abstract class UIElement : Tree<UIElement>, IDisposable, IMobile
    {
        internal static UIElement __PrevHandledElement;
        internal static UIElement __HandledElement;
        /// <summary>当前帧的事件是否已经被消耗掉</summary>
        public static bool Handled
        {
            get { return __HandledElement != null; }
        }
        public void Handle()
        {
            __HandledElement = this;
            //_LOG.Debug("Handle {0} Stack: {1}", this.GetType().Name, Environment.StackTrace);
        }

        protected internal static UIElement FocusedElement { get; private set; }
        public static DUpdateGlobal GlobalEnter;
        public static DUpdateGlobal GlobalHover;
        public static DUpdateGlobal GlobalUnHover;
        public static DUpdateGlobal GlobalClick;
        public static DUpdateGlobal GlobalClicked;

        public string Name;
        public UIFlowLayout Flow;
        /// <summary>UI特效</summary>
        public UIEffect Effect { get; private set; }
        private RECT clip;
        private RECT autoClip;
        private MATRIX2x3 model = MATRIX2x3.Identity;
        public SHADER Shader;
        public bool Enable = true;
        public bool Eventable = true;
        public bool Visible = true;
        public EAnchor Anchor = EAnchor.Left | EAnchor.Top;
        public COLOR Color = COLOR.Default;
        private bool isClip = true;
        private EPivot pivot;
        public object Tag;
        public event Action<VECTOR2> ContentSizeChanged;
        public DUpdate<UIElement> UpdateBegin;
        public DUpdate<UIElement> UpdateEnd;
        public DUpdate<UIElement> EventBegin;
        public DUpdate<UIElement> EventEnd;
        public DDraw<UIElement> DrawBeforeBegin;
        public DDraw<UIElement> DrawAfterBegin;
        public DDraw<UIElement> DrawBeforeChilds;
        public DDraw<UIElement> DrawBeforeEnd;
        public DDraw<UIElement> DrawFocus;
        public DDraw<UIElement> DrawAfterEnd;
        private List<Action<Entry>> events = new List<Action<Entry>>();
        /// <summary>鼠标进入区域内</summary>
        public event DUpdate<UIElement> Enter;
        /// <summary>鼠标在区域内移动</summary>
        public event DUpdate<UIElement> Move;
        /// <summary>鼠标离开区域</summary>
        public event DUpdate<UIElement> Exit;
        /// <summary>获得焦点</summary>
        public event DUpdate<UIElement> Focus;
        /// <summary>失去焦点</summary>
        public event DUpdate<UIElement> Blur;
        /// <summary>鼠标在区域内（不包含进入区域的一次）</summary>
        public event DUpdate<UIElement> Hover;
        /// <summary>鼠标不在区域内</summary>
        public event DUpdate<UIElement> UnHover;
        /// <summary>鼠标左键按下</summary>
        public event DUpdate<UIElement> Click;
        /// <summary>鼠标左键按住拖拽，并指针在目标范围内</summary>
        public event DUpdate<UIElement> Pressed;
        /// <summary>鼠标左键按住拖拽</summary>
        public event DUpdate<UIElement> Drag;
        /// <summary>鼠标左键抬起，需要触发过点击</summary>
        public event DUpdate<UIElement> Clicked;
        /// <summary>鼠标左键抬起</summary>
        public event DUpdate<UIElement> Released;
        /// <summary>鼠标左键双击</summary>
        public event DUpdate<UIElement> DoubleClick;
        /// <summary>轻击事件</summary>
        public event DUpdate<UIElement> Tap;
        /// <summary>键盘按键状态改变</summary>
        public event DUpdate<UIElement> Keyboard;

        private bool needUpdateLocalToWorld = true;
        /// <summary>
        /// 当一个子场景在主场景中时
        /// Entry对场景的更新是从后往前的，即子场景会先更新
        /// 对于Touch来说，前一帧没有按下时，自场景和父场景的Hover状态都是false
        /// 当前帧按下时，父场景由于Hover是false，会导致子场景的Hover也是false
        /// 所以此时应该像needUpdateLocalToWorld时先去更新父场景的Hover状态
        /// </summary>
        private bool needUpdateHover = true;
        private MATRIX2x3 world = MATRIX2x3.Identity;
        private MATRIX2x3 worldInvert = MATRIX2x3.Identity;
        protected VECTOR2 contentSize = VECTOR2.NaN;
        private int sortZ = -1;
        private bool needSort;
        protected bool isHover;
        private bool isClick;
        /// <summary>viewport in Parent</summary>
        private RECT finalClip;
        /// <summary>graphics viewport in screen</summary>
        private RECT finalViewClip;
        private UIElement[] drawOrder;
        private bool isTopMost;

        internal virtual bool IsScene
        {
            get { return false; }
        }
        protected internal bool NeedUpdateLocalToWorld
        {
            get { return needUpdateLocalToWorld; }
            set
            {
                if (!needUpdateLocalToWorld && value)
                {
                    //foreach (UIElement child in this)
                    for (int i = 0; i < Childs.Count; i++)
                    {
                        Childs[i].NeedUpdateLocalToWorld = value;
                    }
                    //needUpdateLocalToWorld = value;
                }
                needUpdateLocalToWorld = value;
            }
        }
        public MATRIX2x3 Model
        {
            get { return model; }
            set
            {
                model = value;
                NeedUpdateLocalToWorld = true;
            }
        }
        public MATRIX2x3 World
        {
            get { return world; }
        }
        /// <summary>当前控件所在场景</summary>
        public UIScene Scene
        {
            get
            {
                UIElement i = this;
                while (true)
                {
                    if (i.Parent == null)
                    {
                        if (i.IsScene)
                            return (UIScene)i;
                        else
                            return null;
                    }
                    else
                    {
                        if (i.Parent.IsScene)
                            return (UIScene)i.Parent;
                        else
                            i = i.Parent;
                    }
                }
            }
        }
        /// <summary>当前控件所在顶级场景</summary>
        public UIScene SceneIsRunning
        {
            get
            {
                UIElement i = this;
                while (true)
                {
                    if (i.Parent == null)
                        if (i.IsScene)
                            return (UIScene)i;
                        else
                            return null;
                    i = i.Parent;
                }
            }
        }
        /// <summary>控件是否能拥有焦点</summary>
        public virtual bool CanFocused
        {
            get { return false; }
        }
        /// <summary>控件当前是否有焦点</summary>
        public bool Focused
        {
            get { return FocusedElement == this; }
            set { SetFocus(value); }
        }
        /// <summary>相对当前控件，下一个获取焦点的控件</summary>
        public UIElement NextFocusedElement
        {
            get
            {
                // 检查子对象是否可以设置焦点
                UIElement result = this.CanFocusChild;
                if (result != null)
                {
                    return result;
                }

                for (UIElement parent = Parent, child = this; parent != null; child = parent, parent = parent.Parent)
                {
                    int index = parent.Childs.IndexOf(child);
                    for (int i = index + 1; i < parent.Childs.Count; i++)
                    {
                        // 检查父对象是否可以设置焦点
                        if (parent.Childs[i].CanFocused && parent.Childs[i].IsEventable)
                        {
                            return parent.Childs[i];
                        }
                        // 检查父对象的所有子对象是否可以设置焦点
                        result = parent.Childs[i].CanFocusChild;
                        if (result != null)
                        {
                            return result;
                        }
                    }
                }

                // 最后的焦点控件到头则为无焦点
                return null;
            }
        }
        private UIElement CanFocusChild
        {
            get
            {
                if (!IsEventable)
                    return null;

                UIElement result;
                for (int i = 0; i < Childs.Count; i++)
                {
                    result = Childs[i];
                    if (result.CanFocused && result.IsEventable)
                    {
                        return result;
                    }

                    result = result.CanFocusChild;
                    if (result != null)
                    {
                        return result;
                    }
                }
                return null;
            }
        }

        /// <summary>控件所在横坐标</summary>
        public float X
        {
            get { return clip.X; }
            set
            {
                if (X != value)
                {
                    clip.X = value;
                    NeedUpdateLocalToWorld = true;
                }
            }
        }
        /// <summary>控件所在纵坐标</summary>
        public float Y
        {
            get { return clip.Y; }
            set
            {
                if (Y != value)
                {
                    clip.Y = value;
                    NeedUpdateLocalToWorld = true;
                }
            }
        }
        /// <summary>控件所在坐标</summary>
        public VECTOR2 Location
        {
            get { return new VECTOR2(X, Y); }
            set
            {
                X = value.X;
                Y = value.Y;
            }
        }
        /// <summary>控件宽，0代表自动</summary>
        public virtual float Width
        {
            get { return Clip.Width; }
            set
            {
                float width = this.Width;
                if (clip.Width != 0 && value == 0)
                {
                    contentSize.X = float.NaN;
                    contentSize.Y = 0;
                }
                clip.Width = value;
                NeedUpdateLocalToWorld = true;
                UpdateWidth(width, this.Width);
            }
        }
        /// <summary>控件高，0代表自动</summary>
        public virtual float Height
        {
            get { return Clip.Height; }
            set
            {
                float height = this.Height;
                if (clip.Height != 0 && value == 0)
                {
                    contentSize.X = 0;
                    contentSize.Y = float.NaN;
                }
                clip.Height = value;
                NeedUpdateLocalToWorld = true;
                UpdateHeight(height, this.Height);
            }
        }
        /// <summary>控件尺寸</summary>
        public VECTOR2 Size
        {
            get { return new VECTOR2(Width, Height); }
            set
            {
                Width = value.X;
                Height = value.Y;
            }
        }
        /// <summary>控件所在区域</summary>
        public RECT Clip
        {
            get
            {
                if (!needUpdateLocalToWorld && float.IsNaN(contentSize.X) && float.IsNaN(contentSize.Y)) return clip;
                if (!IsAutoClip)
                {
                    return clip;
                }
                else
                {
                    //RECT autoClip = new RECT();
                    autoClip.X = X;
                    autoClip.Y = Y;

                    // 效率非常低下
                    //if (needUpdateLocalToWorld)
                    //    UpdateContent();
                    //if (Parent == null)
                    //    UpdateContent();

                    bool flag = false;
                    if (clip.Width == 0 && contentSize.X != autoClip.Width)
                        flag = true;
                    if (!flag && clip.Height == 0 && contentSize.Y != autoClip.Height)
                        flag = true;
                    if (flag)
                        UpdateContent();
                    SetAutoSize();

                    return autoClip;
                }
            }
            set
            {
                X = value.X;
                Y = value.Y;
                Width = value.Width;
                Height = value.Height;
            }
        }
        /// <summary>控件是否自动尺寸</summary>
        public bool IsAutoClip
        {
            get { return clip.Width == 0 || clip.Height == 0; }
        }
        /// <summary>控件宽是否自动</summary>
        public bool IsAutoWidth
        {
            get { return clip.Width == 0; }
        }
        /// <summary>控件高是否自动</summary>
        public bool IsAutoHeight
        {
            get { return clip.Height == 0; }
        }
        /// <summary>控件在父控件内的所在区域</summary>
        public RECT InParentClip
        {
            get { return InParent(Clip); }
        }
        /// <summary>控件内容尺寸</summary>
        public virtual VECTOR2 ContentSize
        {
            get
            {
                RECT clip = ChildClip;
                return new VECTOR2(clip.Right, clip.Bottom);
                //return ChildClip.Size;
            }
        }
        /// <summary>子控件的区域</summary>
        public virtual RECT ChildClip
        {
            get
            {
                return CalcChildClip(this, DefaultChildClip);
            }
        }
        public RECT InParentChildClip
        {
            get { return InParent(ChildClip); }
        }
        /// <summary>控件的锚点对齐方式</summary>
        public EPivot Pivot
        {
            get { return pivot; }
            set
            {
                if (pivot != value)
                {
                    pivot = value;
                    NeedUpdateLocalToWorld = true;
                }
            }
        }
        /// <summary>控件的锚点坐标</summary>
        public VECTOR2 PivotPoint
        {
            get
            {
                VECTOR2 size = Size;
                return new VECTOR2(PivotAlignmentX * size.X * 0.5f, PivotAlignmentY * size.Y * 0.5f);
            }
        }
        /// <summary>控件对齐横向：左0/中1/右2</summary>
        public int PivotAlignmentX
        {
            get { return (int)pivot & 0x0f; }
            set { Pivot = (EPivot)(value + (PivotAlignmentY >> 4)); }
        }
        /// <summary>控件对齐纵向：上0/中1/下2</summary>
        public int PivotAlignmentY
        {
            get { return ((int)pivot & 0xf0) >> 4; }
            set { Pivot = (EPivot)(PivotAlignmentX + (value >> 4)); }
        }
        /// <summary>约束子控件是否在自己的可视范围内才让有效</summary>
        public bool IsClip
        {
            get { return isClip; }
            set
            {
                if (isClip != value)
                {
                    isClip = value;
                    NeedUpdateLocalToWorld = true;
                }
            }
        }
        /// <summary>当前帧鼠标是否悬浮在控件区域内</summary>
        public bool IsHover
        {
            get { return isHover; }
        }
        /// <summary>当前帧鼠标是否在控件区域内点击过</summary>
        public bool IsClick
        {
            get { return isClick; }
        }
        /// <summary>控件绘制的先后顺序</summary>
        public int SortZ
        {
            get { return sortZ; }
            set
            {
                if (sortZ != value)
                {
                    sortZ = value;
                    if (Parent != null)
                    {
                        Parent.needSort = true;
                    }
                }
            }
        }
        /// <summary>当前帧鼠标是否悬浮在控件及其任一子控件区域内</summary>
        public bool FinalHover
        {
            get
            {
                for (int i = 0; i < Childs.Count; i++)
                {
                    if (Childs[i].FinalHover)
                    {
                        return true;
                    }
                }
                return isHover;
            }
        }
        public bool FinalEnable
        {
            get
            {
                for (UIElement i = this; i != null; i = i.Parent)
                {
                    if (!i.IsEnable)
                    {
                        return false;
                    }
                }
                return true;
            }
        }
        public bool FinalEventable
        {
            get
            {
                for (UIElement i = this; i != null; i = i.Parent)
                {
                    if (!i.IsEventable)
                    {
                        return false;
                    }
                }
                return true;
            }
        }
        public bool FinalVisible
        {
            get
            {
                for (UIElement i = this; i != null; i = i.Parent)
                {
                    if (!i.IsVisible)
                    {
                        return false;
                    }
                }
                return true;
            }
        }
        public bool IsEnable
        {
            get { return Enable && IsVisible; }
        }
        public bool IsEventable
        {
            get { return Eventable && IsVisible; }
        }
        /// <summary>控件是否可见</summary>
        public bool IsVisible
        {
            //get { return Visible && Color.A > 0; }
            get { return Visible; }
        }
        protected bool NeedDrawChild
        {
            get
            {
                if (drawOrder == null || drawOrder.Length == 0)
                    return false;

                if (!IsVisible)
                    return false;

                //for (int i = 0; i < drawOrder.Length; i++)
                //{
                //    if (drawOrder[i].IsVisible && !drawOrder[i].drawTopMost)
                //    {
                //        return true;
                //    }
                //}
                //return false;

                return true;
            }
        }
        /// <summary>控件视图的绘制区域</summary>
        public virtual RECT ViewClip
        {
            get
            {
                if (needUpdateLocalToWorld)
                {
                    var temp = finalClip;
                    temp.Width = Width;
                    temp.Height = Height;
                    return temp;
                }
                return finalClip;
            }
        }
        public RECT FinalViewClip
        {
            get { return finalViewClip; }
        }
        /// <summary>UI类型</summary>
        public virtual EUIType UIType { get { return EUIType.UIElement; } }

        public UIElement()
        {
            if (UIStyle.Style != null)
            {
                UIStyle.Style.FitStyle(this);
            }
            Effect = new UIEffect(this);
            RegistEvent(DoEnter);
            RegistEvent(DoMove);
            RegistEvent(DoExit);
            RegistEvent(DoHover);
            RegistEvent(DoUnHover);
            RegistEvent(DoDoubleClick);
            RegistEvent(DoClick);
            RegistEvent(DoPressed);
            RegistEvent(DoDrag);
            RegistEvent(DoClicked);
            RegistEvent(DoReleased);
            RegistEvent(DoTap);
            RegistEvent(DoKeyboard);
        }

        public void Update(Entry e)
        {
            UpdateLocalToWorld();

            if (!IsEnable)
                return;

            if (UpdateBegin != null)
                UpdateBegin(this, e);

            InternalUpdate(e);
            for (int i = Childs.Count - 1; i >= 0 && i < Childs.Count; i--)
            {
                //if (Handled)
                //    break;
                if (!Childs[i].IsScene || ((UIScene)Childs[i]).Entry == null)
                    Childs[i].Update(e);
            }

            if (UpdateEnd != null)
                UpdateEnd(this, e);
        }
        public void Event(Entry e)
        {
            UpdateLocalToWorld();

            var pointer = e.INPUT.Pointer;
            UpdateHoverState(pointer);

            if (!isClick)
            {
                isClick = isHover && pointer.IsClick(pointer.DefaultKey);
            }

            bool __event = FinalEventable;
            if (__event && !Handled && EventBegin != null)
                EventBegin(this, e);

            for (int i = Childs.Count - 1; i >= 0 && i < Childs.Count; i--)
            {
                //if (Handled)
                //    break;
                if (!Childs[i].IsScene || ((UIScene)Childs[i]).Entry == null)
                    Childs[i].Event(e);
            }

            if (__event && !Handled)
            {
                for (int i = 0; i < events.Count; i++)
                {
                    if (Handled)
                        break;
                    events[i](e);
                }
                if (!Handled)
                    InternalEvent(e);
            }

            if (__event && !Handled && EventEnd != null)
                EventEnd(this, e);

            if (isClick)
            {
                //if ((__HandledElement != null && __HandledElement != this) || (__PrevHandledElement != null && __PrevHandledElement != this))
                //{
                //    isClick = false;
                //}
                //else
                {
                    isClick = pointer.IsPressed(pointer.DefaultKey) ||
                        // Invoke "IsClick" is true in parent InternalEvent
                        pointer.IsRelease(pointer.DefaultKey);
                }
            }

            needUpdateHover = true;
        }
        public void Draw(GRAPHICS spriteBatch, Entry e)
        {
            UpdateLocalToWorld();
            isTopMost = false;

            if (!IsVisible)
                return;

            UpdateSort();
            UpdateContent();

            if (DrawBeforeBegin != null)
            {
                DrawBeforeBegin(this, spriteBatch, e);
            }

            DrawBegin(spriteBatch, ref model, ref finalViewClip, Shader);

            if (DrawAfterBegin != null)
            {
                DrawAfterBegin(this, spriteBatch, e);
            }

            bool effectDraw = !Effect.IsEnd;
            if (effectDraw)
            {
                Effect.Update(e.GameTime.ElapsedSecond);
                Effect.Begin(spriteBatch);
            }

            InternalDraw(spriteBatch, e);
            if (DrawBeforeChilds != null)
            {
                DrawBeforeChilds(this, spriteBatch, e);
            }
            if (NeedDrawChild)
            {
                for (int i = 0; i < drawOrder.Length; i++)
                {
                    if (drawOrder[i].isTopMost)
                        continue;
                    if (drawOrder[i].IsScene)
                    {
                        var scene = (UIScene)drawOrder[i];
                        // 主场景内显示的普通场景，这里不能渲染
                        if (scene.Entry != null)
                            continue;
                        //if (!(scene.Entry == null || (!scene.DrawState && scene.IsDrawable)))
                        //    continue;
                    }
                    drawOrder[i].Draw(spriteBatch, e);
                    //var scene = drawOrder[i] as UIScene;
                    //if (scene == null || scene.Entry == null || (!scene.DrawState && scene.IsDrawable))
                    //    drawOrder[i].Draw(spriteBatch, e);
                }
            }
            InternalDrawAfter(spriteBatch, e);

            if (effectDraw)
                spriteBatch.End();

            if (DrawBeforeEnd != null)
            {
                DrawBeforeEnd(this, spriteBatch, e);
            }

            DrawEnd(spriteBatch, ref model, ref finalViewClip, Shader);

            if (DrawAfterEnd != null)
            {
                DrawAfterEnd(this, spriteBatch, e);
                if (DrawFocus != null)
                {
                    DrawFocus(this, spriteBatch, e);
                }
            }

            var scene2 = SceneIsRunning;
            if (scene2 != null && scene2.IsInStage && scene2.UseFlowLayout)
            {
                var clip = ViewClip;
                clip.Width += Flow.MaginLeft + Flow.MaginRight;
                clip.X -= Flow.MaginLeft;
                if (Flow.Line)
                    clip.Width = Parent.Width - clip.X;
                clip.Height += Flow.MaginTop + Flow.MaginBottom;
                clip.Y -= Flow.MaginTop;

                //spriteBatch.Draw(patch, clip);
            }
        }
        protected virtual void DrawBegin(GRAPHICS spriteBatch, ref MATRIX2x3 transform, ref RECT view, SHADER shader)
        {
        }
        protected virtual void DrawEnd(GRAPHICS spriteBatch, ref MATRIX2x3 transform, ref RECT view, SHADER shader)
        {
        }
        private void UpdateSort()
        {
            if (needSort)
            {
                drawOrder = Childs.ToArray();
                Utility.SortOrderAsc(drawOrder, e => e.sortZ);
                needSort = false;
                OnUpdateSort(drawOrder);
            }
        }
        protected virtual void OnUpdateSort(UIElement[] drawOrder)
        {
        }
        internal void UpdateHoverState(IPointer pointer)
        {
            if (needUpdateHover)
            {
                if (!pointer.Position.IsNaN())
                {
                    if (FinalVisible)
                        isHover = IsContains(pointer.Position);
                    else
                        isHover = false;
                }
                else if (!pointer.PositionPrevious.IsNaN())
                {
                    if (FinalVisible)
                        isHover = IsContains(pointer.PositionPrevious);
                    else
                        isHover = false;
                }
                else
                {
                    isHover = false;
                }
                needUpdateHover = false;
            }
        }
        private void UpdateLocalToWorld()
        {
            UpdateContent();
            if (NeedUpdateLocalToWorld)
            {
                if (Parent != null)
                    Parent.UpdateLocalToWorld();

                UpdateTranslation(ref model);

                if (Parent != null)
                    world = model * Parent.world;
                else
                    world = model;

                UpdateTransformEnd(ref model, ref world);

                UpdateClip(ref finalClip, ref finalViewClip, ref model, ref world);

                MATRIX2x3.Invert(ref world, out worldInvert);
                needUpdateLocalToWorld = false;
            }
        }
        protected virtual void UpdateTranslation(ref MATRIX2x3 transform)
        {
            transform.M31 = X;
            transform.M32 = Y;

            float pivotX = PivotAlignmentX * Width * 0.5f;
            float pivotY = PivotAlignmentY * Height * 0.5f;
            transform.M31 -= transform.M11 * pivotX + transform.M21 * pivotY;
            transform.M32 -= transform.M12 * pivotX + transform.M22 * pivotY;
        }
        protected virtual void UpdateClip(ref RECT finalClip, ref RECT finalViewClip, ref MATRIX2x3 transform, ref MATRIX2x3 localToWorld)
        {
            RECT clip = Clip;
            finalClip = clip;
            finalClip.X = localToWorld.M31;
            finalClip.Y = localToWorld.M32;

            bool scissor = Parent != null && Parent.isClip;
            finalViewClip = finalClip;
            if (scissor)
            {
                RECT.Intersect(ref finalViewClip, ref Parent.finalViewClip, out finalViewClip);
            }
        }
        protected virtual void UpdateTransformEnd(ref MATRIX2x3 transform, ref MATRIX2x3 localToWorld)
        {
        }
        public void ResetContentSize()
        {
            contentSize = VECTOR2.NaN;
            //contentSize.X = 0;
            //contentSize.Y = 0;
        }
        private void UpdateContent()
        {
            if (IsNeedUpdateContent())
            {
                VECTOR2 size = ContentSize;
                if (contentSize.X != size.X || contentSize.Y != size.Y)
                {
                    //_LOG.Debug("ContentSize X:{0} Y:{1} Stack:{2}", size.X, size.Y, Environment.StackTrace);
                    NeedUpdateLocalToWorld = true;
                    if (IsAutoWidth && contentSize.X != size.X)
                        UpdateWidth(contentSize.X, size.X);
                    contentSize.X = size.X;
                    if (IsAutoHeight && contentSize.Y != size.Y)
                        UpdateHeight(contentSize.Y, size.Y);
                    contentSize.Y = size.Y;
                    if (ContentSizeChanged != null)
                    {
                        SetAutoSize();
                        ContentSizeChanged(size);
                    }
                }
            }
        }
        private void SetAutoSize()
        {
            if (clip.Width == 0)
                autoClip.Width = contentSize.X;
            else
                autoClip.Width = clip.Width;
            if (clip.Height == 0)
                autoClip.Height = contentSize.Y;
            else
                autoClip.Height = clip.Height;
        }
        protected virtual bool IsNeedUpdateContent()
        {
            return IsAutoClip;
        }
        /// <summary>每帧更新逻辑</summary>
        protected virtual void InternalUpdate(Entry e)
        {
        }
        /// <summary>每帧事件逻辑</summary>
        protected virtual void InternalEvent(Entry e)
        {
        }
        /// <summary>绘制子控件前执行，这里绘制的内容会被子控件遮挡</summary>
        protected virtual void InternalDraw(GRAPHICS spriteBatch, Entry e)
        {
        }
        /// <summary>绘制子控件后绘制，这里绘制的内容会遮挡子控件</summary>
        protected virtual void InternalDrawAfter(GRAPHICS spriteBatch, Entry e)
        {
        }
        public void DrawTopMost()
        {
            DrawTopMost(Scene);
        }
        public void DrawTopMost(UIScene scene)
        {
            if (isTopMost || scene == this || scene == null)
                return;
            isTopMost = true;
            scene.TopMost.Enqueue(this);
        }
        public bool SkipDraw()
        {
            UIScene top = Scene;
            if (top == this || top == null)
                return false;

            if (isTopMost && top.TopMost.Count > 0)
            {
                UIElement peek = top.TopMost.Peek();
                if (peek == this)
                {
                    top.TopMost.Dequeue();
                }
                else
                {
                    throw new InvalidOperationException("SkipDraw should be called before DrawTopMost and can't invoke repeated");
                }
            }
            else
            {
                isTopMost = true;
            }
            return isTopMost;
        }
        public virtual void ToFront()
        {
            if (Parent == null)
                return;

            if (Parent.Childs.Remove(this))
            {
                Parent.Childs.Add(this);
                needSort = true;
            }
        }
        public virtual void ToBack()
        {
            if (Parent == null)
                return;

            if (Parent.Childs.Remove(this))
            {
                Parent.Childs.Insert(0, this);
                needSort = true;
            }
        }

        public void AddChildFirst(UIElement node)
        {
            Insert(node, 0);
        }
        protected override bool CheckAdd(UIElement node)
        {
            return Childs.IndexOf(node) == -1;
        }
        protected override void OnAdded(UIElement node, int index)
        {
            //child.UpdateLocalToWorld();
            needSort = true;
            NeedUpdateLocalToWorld = true;
        }
        protected override void OnRemoved(UIElement node)
        {
            needSort = true;
            //NeedUpdateLocalToWorld = true;
        }
        protected void InsertChildBefore(UIElement element, UIElement target)
        {
            int index = Childs.IndexOf(target);
            if (index == -1)
                Insert(element, 0);
            else
                Insert(element, index);
        }
        protected void InsertChildAfter(UIElement element, UIElement target)
        {
            int index = Childs.IndexOf(target);
            if (index == -1)
                Add(element);
            else
                Insert(element, index + 1);
        }
        private void UpdateWidth(float srcWidth, float dstWidth)
        {
            // UI编辑器 -> 读取TabPage.Page -> 读取TabPage.Parent.Clip -> 导致Page尺寸拉大
            if (srcWidth == 0 || float.IsNaN(srcWidth) || srcWidth == dstWidth)
                return;

            float add = dstWidth - srcWidth;
            float mul = srcWidth == 0 ? 0 : dstWidth / srcWidth;
            for (int i = 0; i < Childs.Count; i++)
            {
                var child = Childs[i];
                bool left = (child.Anchor & EAnchor.Left) == EAnchor.Left;
                bool right = (child.Anchor & EAnchor.Right) == EAnchor.Right;
                bool center = (child.Anchor & EAnchor.Center) == EAnchor.Center;

                if (center)
                {
                    if (left && right)
                    {
                        child.X *= mul;
                        child.Width *= mul;
                    }
                    else if (right)
                    {
                        child.X = (child.X + child.Width) * mul - child.Width;
                        //child.X = child.X * mul + child.Width * (mul - 1);
                    }
                    else
                    {
                        child.X *= mul;
                    }
                }
                else
                {
                    if (left && right)
                    {
                        child.Width += add;
                    }
                    else if (right)
                    {
                        child.X += add;
                    }
                }
            }
        }
        private void UpdateHeight(float srcHeight, float dstHeight)
        {
            if (srcHeight == 0 || float.IsNaN(srcHeight) || srcHeight == dstHeight)
                return;

            float add = dstHeight - srcHeight;
            float mul = srcHeight == 0 ? 0 : dstHeight / srcHeight;
            for (int i = 0; i < Childs.Count; i++)
            {
                var child = Childs[i];
                bool top = (child.Anchor & EAnchor.Top) == EAnchor.Top;
                bool bottom = (child.Anchor & EAnchor.Bottom) == EAnchor.Bottom;
                bool middle = (child.Anchor & EAnchor.Middle) == EAnchor.Middle;

                if (middle)
                {
                    if (top && bottom)
                    {
                        child.Y *= mul;
                        child.Height *= mul;
                    }
                    else if (bottom)
                    {
                        child.Y = (child.Y + child.Height) * mul - child.Height;
                        //child.Y = child.Y * mul + child.Height * (mul - 1);
                    }
                    else
                    {
                        child.Y *= mul;
                    }
                }
                else
                {
                    if (top && bottom)
                    {
                        child.Height += add;
                    }
                    else if (bottom)
                    {
                        child.Y += add;
                    }
                }
            }
        }
        public virtual bool IsContains(VECTOR2 graphicsPosition)
        {
            return InParentClip.Contains(ConvertGraphicsToLocalView(graphicsPosition));
        }
        public RECT InParent(RECT clip)
        {
            InParent(ref clip.X, ref clip.Y);
            return clip;
        }
        /// <summary>根据Pivot将范围转换成在自己父容器中的位置</summary>
        public void InParent(ref float x, ref float y)
        {
            x -= PivotAlignmentX * Width * 0.5f;
            y -= PivotAlignmentY * Height * 0.5f;
            if (!needUpdateLocalToWorld && (x != model.M31 || y != model.M32))
            {
                x = model.M31;
                y = model.M32;
            }
        }
        public VECTOR2 ConvertGraphicsToLocalView(VECTOR2 point)
        {
            if (Parent != null)
            {
                if (Parent.isClip && !Parent.isHover)
                {
                    point = VECTOR2.NaN;
                }
                else
                {
                    point = Parent.ConvertGraphicsToLocal(point);
                }
            }
            return point;
        }
        public VECTOR2 ConvertGraphicsToLocal(VECTOR2 point)
        {
            VECTOR2.Transform(ref point, ref worldInvert);
            return point;
        }
        public VECTOR2 ConvertLocalToGraphics(VECTOR2 point)
        {
            VECTOR2.Transform(ref point, ref world);
            return point;
        }
        public VECTOR2 ConvertLocalToOther(VECTOR2 point, UIElement other)
        {
            VECTOR2 result;
            result = ConvertLocalToGraphics(point);
            if (other != null)
                result = other.ConvertGraphicsToLocal(result);
            return result;
        }
        public bool SetFocus(bool focus)
        {
            if (focus)
            {
                if (FocusedElement != null && FocusedElement != this)
                {
                    //focusedElement.OnBlur();
                    FocusedElement.SetFocus(false);
                }
                if (!CanFocused)
                {
                    return false;
                }
                FocusedElement = this;
                this.OnFocus();
                return true;
            }
            else
            {
                if (Focused)
                {
                    FocusedElement = null;
                    OnBlur();
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        public override string ToString()
        {
            if (string.IsNullOrEmpty(Name))
                return base.ToString();
            else
                return base.ToString() + ": " + Name;
        }
        public virtual void Dispose()
        {
            for (int i = 0; i < Childs.Count; i++)
            {
                Childs[i].Dispose();
            }
        }

        protected void RegistEvent(Action<Entry> e)
        {
            if (e == null)
                throw new ArgumentNullException("Event");
            events.Add(e);
        }
        protected bool OnEnter(Entry e)
        {
            return isHover && !IsContains(e.INPUT.Pointer.PositionPrevious);
        }
        private void DoEnter(Entry e)
        {
            if (GlobalEnter == null && Enter == null) return;
            bool enter = OnEnter(e);
            if (Enter != null && enter)
            {
                Enter(this, e);
            }
            if (GlobalEnter != null && enter)
            {
                GlobalEnter(this, Enter != null, e);
            }
        }
        protected bool OnMove(Entry e)
        {
            if (isHover)
            {
                VECTOR2 moved = e.INPUT.Pointer.DeltaPosition;
                if (!moved.IsNaN() && moved.X != 0 && moved.Y != 0)
                {
                    return true;
                }
            }
            return false;
        }
        private void DoMove(Entry e)
        {
            if (Move != null && OnMove(e))
            {
                Move(this, e);
            }
        }
        protected bool OnExit(Entry e)
        {
            return !isHover && IsContains(e.INPUT.Pointer.PositionPrevious);
        }
        private void DoExit(Entry e)
        {
            if (Exit != null && OnExit(e))
            {
                Exit(this, e);
            }
        }
        protected virtual void OnFocus()
        {
            if (Focus != null)
            {
                Focus(this, Entry.Instance);
            }
        }
        protected virtual void OnBlur()
        {
            if (Blur != null)
            {
                Blur(this, Entry.Instance);
            }
        }
        private void DoHover(Entry e)
        {
            if (Hover != null && isHover)
            {
                Hover(this, e);
            }
            if (GlobalHover != null && isHover)
            {
                GlobalHover(this, Hover != null, e);
            }
        }
        private void DoUnHover(Entry e)
        {
            if (UnHover != null && !isHover)
            {
                UnHover(this, e);
            }
            if (GlobalUnHover != null && !isHover)
            {
                GlobalUnHover(this, UnHover != null, e);
            }
        }
        protected bool OnClick(Entry e)
        {
            return isHover && e.INPUT.Pointer.IsClick(e.INPUT.Pointer.DefaultKey);
        }
        private void DoClick(Entry e)
        {
            if (Focused && e.INPUT.Pointer.IsClick(e.INPUT.Pointer.DefaultKey) && !isHover)
            {
                SetFocus(false);
            }
            if (Click == null && GlobalClick == null) return;
            bool flag = OnClick(e);
            if (Click != null && flag)
            {
                Click(this, e);
                Handle();
            }
            if (GlobalClick != null && flag)
            {
                GlobalClick(this, Click != null, e);
                Handle();
            }
        }
        protected bool OnPressed(Entry e)
        {
            return isClick && isHover && e.INPUT.Pointer.IsPressed(e.INPUT.Pointer.DefaultKey);
        }
        private void DoPressed(Entry e)
        {
            if (Pressed != null && OnPressed(e))
            {
                Pressed(this, e);
            }
        }
        protected bool OnDrag(Entry e)
        {
            return isClick && e.INPUT.Pointer.IsPressed(e.INPUT.Pointer.DefaultKey);
        }
        private void DoDrag(Entry e)
        {
            if (Drag != null && OnDrag(e))
            {
                Drag(this, e);
            }
        }
        protected bool OnClicked(Entry e)
        {
            // e.INPUT.Pointer.IsRelease(e.INPUT.Pointer.DefaultKey)
            // e.INPUT.Pointer.IsTap(e.INPUT.Pointer.DefaultKey)
            return isHover && isClick && e.INPUT.Pointer.IsRelease(e.INPUT.Pointer.DefaultKey);
        }
        private void DoClicked(Entry e)
        {
            if (Clicked == null && GlobalClicked == null) return;
            bool flag = OnClicked(e);
            if (Clicked != null && flag)
            {
                Clicked(this, e);
                Handle();
            }
            if (GlobalClicked != null && flag)
            {
                GlobalClicked(this, Clicked != null, e);
                Handle();
            }
        }
        protected bool OnReleased(Entry e)
        {
            return isHover && e.INPUT.Pointer.IsRelease(e.INPUT.Pointer.DefaultKey);
        }
        private void DoReleased(Entry e)
        {
            if (Released != null && OnReleased(e))
            {
                Released(this, e);
                Handle();
            }
        }
        protected bool OnTap(Entry e)
        {
            return isHover && isClick && e.INPUT.Pointer.IsTap(e.INPUT.Pointer.DefaultKey);
        }
        private void DoTap(Entry e)
        {
            if (Tap != null && OnTap(e))
            {
                Tap(this, e);
                Handle();
            }
        }
        protected bool OnDoubleClick(Entry e)
        {
            return isHover && e.INPUT.Pointer.ComboClick.IsDoubleClick;
        }
        private void DoDoubleClick(Entry e)
        {
            if (DoubleClick != null && OnDoubleClick(e))
            {
                DoubleClick(this, e);
                Handle();
            }
        }
        protected bool OnKeyboard(Entry e)
        {
            return e.INPUT.Keyboard != null && e.INPUT.Keyboard.Focused;
        }
        private void DoKeyboard(Entry e)
        {
            if (Keyboard != null && OnKeyboard(e))
            {
                Keyboard(this, e);
            }
        }

        public static RECT CalcChildClip(UIElement parent, Func<UIElement, RECT> clipGenerator)
        {
            if (parent.Childs.Count == 0)
                return RECT.Empty;
            RECT clip = new RECT(int.MaxValue, int.MaxValue, int.MinValue, int.MinValue);
            foreach (UIElement child in parent.Childs)
            {
                RECT temp = clipGenerator(child);
                if (temp.Width == 0 || temp.Height == 0)
                    continue;
                clip.X = _MATH.Min(temp.X, clip.X);
                clip.Y = _MATH.Min(temp.Y, clip.Y);
                clip.Width = _MATH.Max(temp.Right, clip.Width);
                clip.Height = _MATH.Max(temp.Bottom, clip.Height);
            }
            clip.Width = clip.Width - clip.X;
            clip.Height = clip.Height - clip.Y;
            return clip;
        }
        /// <summary>计算子控件的区域</summary>
        protected static RECT DefaultChildClip(UIElement child)
        {
            if (!child.Visible)
                return RECT.Empty;
            //if (child is UIScene && ((UIScene)child).IsInStage)
            //    return RECT.Empty;
            RECT rect = child.InParentClip;
            rect.Width = rect.Right;
            rect.Height = rect.Bottom;
            // 子内容没有锁定在范围内时，可能子内容超出了容器
            if (!child.isClip)
            {
                // 获得容器的子内容
                RECT clip = child.ChildClip;
                // 左侧超出的部分
                if (clip.X < 0)
                {
                    rect.X += clip.X;
                    rect.Width -= clip.X;
                }
                // 上侧超出的部分
                if (clip.Y < 0)
                {
                    rect.Y += clip.Y;
                    rect.Height -= clip.Y;
                }
                // 转换成父容器内的坐标，才能与原本父容器内的范围进行比较
                //clip = child.InParent(clip);
                child.InParent(ref clip.X, ref clip.Y);
                // 右侧超出的部分
                if (clip.Right > rect.Width)
                    rect.Width = clip.Right;
                // 下侧超出的部分
                if (clip.Bottom > rect.Height)
                    rect.Height = clip.Bottom;
            }
            rect.Width = rect.Width - rect.X;
            rect.Height = rect.Height - rect.Y;
            return rect;
            //return RECT.Union(child.Clip, child.InParentChildClip);
        }
        public static VECTOR2 CalcPivotPoint(VECTOR2 size, EPivot pivot)
        {
            return new VECTOR2(
                PivotX(pivot) * size.X * 0.5f,
                PivotY(pivot) * size.Y * 0.5f);
        }
        public static int PivotX(EPivot pivot)
        {
            return ((int)pivot) & 15;
        }
        public static int PivotY(EPivot pivot)
        {
            return ((int)pivot) >> 4;
        }
        public static VECTOR2 TextAlign(RECT bound, VECTOR2 textSize, EPivot alignment)
        {
            int px = ((int)alignment) & 15;
            int py = ((int)alignment) >> 4;
            VECTOR2 location = bound.Location;
            location.X += px * bound.Width * 0.5f;
            location.Y += py * bound.Height * 0.5f;
            location.X -= px * textSize.X * 0.5f;
            location.Y -= py * textSize.Y * 0.5f;
            return location;
        }
        /// <summary>文字只能左上角开始绘制，这里计算文字应用了对齐之后的左上角位置</summary>
        /// <param name="bound">文字绘制的区域</param>
        /// <param name="textSize">文字计算出的绘制尺寸，一般由Font.MeasureString乘以缩放计算得出</param>
        /// <param name="alignment">文字对齐方式</param>
        /// <param name="result">计算得出的文字渲染用的左上角位置</param>
        public static void TextAlign(ref RECT bound, ref VECTOR2 textSize, EPivot alignment, out VECTOR2 result)
        {
            int pivotx = PivotX(alignment);
            int pivoty = PivotY(alignment);
            result.X = bound.X + (bound.Width - textSize.X) * pivotx * 0.5f;
            result.Y = bound.Y + (bound.Height - textSize.Y) * pivoty * 0.5f;
        }
        public static UIElement FindElementByPosition(UIElement Parent, VECTOR2 screenPosition)
        {
            return FindChildPriority(Parent, e => !e.IsVisible, e => e.IsContains(screenPosition));
        }
        public static bool FindSkipInvisible(UIElement target)
        {
            return !target.Visible;
        }
        public static bool FindSkipUnhover(UIElement target)
        {
            return !target.isHover;
        }
        /// <summary>向容器里添加一个组件，总体居中对齐，后续添加的向右放</summary>
        /// <param name="space">组件间的间隔</param>
        public static void AddCenterX(UIElement parent, UIElement child, float space)
        {
            parent.Add(child);
            int count = parent.ChildCount;
            if (count == 1)
            {
                // 第一个居中对齐
                child.X = parent.Width * 0.5f + (child.PivotAlignmentX - 1) * child.Width * 0.5f;
                child.Y = parent.Height * 0.5f + (child.PivotAlignmentY - 1) * child.Height * 0.5f;
            }
            else
            {
                var last = parent[count - 2];
                child.X = last.X + last.Width + space;
                child.Y = last.Y;
                // 前面的组件全部向前移
                float left = (last.Width + space) * 0.5f;
                // 最前面一个不能减到负数，即组件过多时，居左对齐
                if (parent[0].X < left)
                    left = parent[0].X;
                if (left > 0)
                    for (int i = 0; i < count; i++)
                        parent[i].X -= left;
            }
        }
    }

    /// <summary>场景流程
    /// <para>1. Ending & Loading同时进行</para>
    /// <para>2. 所有Ending结束，Loading完成的菜单率先进入Preparing，Preparing需要进行绘制，但不进行更新</para>
    /// <para>3. 所有Preparing结束，进入Showing</para>
    /// <para>4. 所有Beginning结束，进入Running</para>
    /// <para>Ending: Update, Draw</para>
    /// <para>Loading:</para>
    /// <para>Preparing: Draw</para>
    /// <para>Showing: Update, Draw</para>
    /// <para>Running: Event, Update, Draw</para>
    /// </summary>
    public enum EPhase
    {
        None,
        /// <summary>场景从舞台移除之前的结束阶段：执行更新，绘制</summary>
        Ending,
        /// <summary>场景进入舞台前的加载阶段：不执行任何流程</summary>
        Loading,
        /// <summary>场景进入舞台前的准备阶段：执行绘制</summary>
        Preparing,
        /// <summary>准备完成阶段，会等待其它场景准备完成：执行绘制</summary>
        Prepared,
        /// <summary>场景进入舞台前的阶段：执行更新，绘制</summary>
        Showing,
        /// <summary>场景正在运行</summary>
        Running,
    }
    /// <summary>场景的更新状态，关系着与其它场景如何交互</summary>
    [Code(ECode.ToBeContinue)]
    public enum EState
    {
        /// <summary>无特别操作</summary>
        None,
        /// <summary>对话框场景：会让其它场景事件无效</summary>
        Dialog,
        /// <summary>对话框场景：会让其它场景事件和更新无效</summary>
        Block,
        /// <summary>子控件场景：会在舞台中加载完成后被移除掉，适用于作为子控件被加入其它控件内</summary>
        Break,
        /// <summary>一次性场景：会在舞台中加载完成后被移除掉并释放资源</summary>
        Dispose,
        /// <summary>一次性场景：会在舞台中加载完成后被移除掉并释放资源，并清除实例在舞台中的缓存</summary>
        Release,
        /// <summary>遮罩场景：绘制主场景和遮罩场景，会让其它场景事件无效</summary>
        Cover,
        /// <summary>遮罩场景：仅绘制遮罩场景，会让其它场景事件和更新无效</summary>
        CoverAll,
    }
    /// <summary>场景的资源管理器</summary>
    public enum EContent
    {
        /// <summary>新建一个资源管理器</summary>
        New,
        /// <summary>继承父场景的资源管理器，没有父场景时，使用系统的资源管理器</summary>
        Inherit,
        /// <summary>使用系统的资源管理器</summary>
        System
    }
    /// <summary>场景出现的位置</summary>
    [Code(ECode.MayBeReform)]
    public enum EShowPosition
    {
        /// <summary>默认使用场景自定义的位置</summary>
        Default,
        /// <summary>父场景的中心</summary>
        ParentCenter,
        [Obsolete]
        GraphicsCenter,
    }
    /// <summary>场景</summary>
    public class UIScene : Panel, IDisposable
    {
        internal EPhase Phase;
        internal COROUTINE Phasing;
        /// <summary>场景的更新状态，关系着与其它场景如何交互</summary>
        public EState State = EState.None;
        /// <summary>场景的资源管理器</summary>
        public EContent ContentType = EContent.Inherit;
        /// <summary>场景出现的位置</summary>
        public EShowPosition ShowPosition;
        /// <summary>让下一个控件获得焦点的键盘按键，默认是Tab键</summary>
        public PCKeys FocusNextKey = PCKeys.Tab;
        public event Action<UIScene, ContentManager> PhaseLoading;
        public event Action<UIScene> PhasePreparing;
        public event Action<UIScene> PhasePrepared;
        public event Action<UIScene> PhaseShowing;
        public event Action<UIScene> PhaseShown;
        public event Action<UIScene> PhaseEnding;
        public event Action<UIScene> PhaseEnded;
        public event Action<UIScene, ContentManager> LoadCompleted;
        internal Queue<UIElement> TopMost = new Queue<UIElement>();
        private List<AsyncLoadContent> loadings = new List<AsyncLoadContent>();
        public bool UseFlowLayout;

        internal override bool IsScene
        {
            get { return true; }
        }
        /// <summary>场景所在舞台，作为其它控件的子控件时，舞台为null</summary>
        public Entry Entry
        {
            get;
            internal set;
        }
        /// <summary>场景的资源管理器</summary>
        public ContentManager Content
        {
            get;
            protected set;
        }
        public bool IsDisposed
        {
            get
            {
                if (Content == null || Content.IsDisposed)
                {
                    return true;
                }
                else
                {
                    if (ContentType == EContent.Inherit && Parent != null && Parent.Scene != null)
                    {
                        return Parent.Scene.IsDisposed;
                    }
                    return false;
                }
            }
        }
        protected IEnumerable<AsyncLoadContent> Loadings
        {
            get { return loadings.Enumerable(); }
        }
        public EPhase RunningState
        {
            get { return Phase; }
        }
        public bool IsInStage
        {
            get { return Entry != null; }
        }
        public override EUIType UIType
        {
            get { return EUIType.UIScene; }
        }

        public UIScene()
        {
            if (Entry._GRAPHICS == null)
                this.Size = new VECTOR2(1280, 720);
            else
                this.Size = Entry._GRAPHICS.GraphicsSize;
            this.Keyboard += DoKeyboard;
        }
        public UIScene(string name)
            : this()
        {
            this.Name = name;
        }

        protected override void OnRemovedBy(UIElement parent)
        {
            Close(true);
        }
        internal void SetPhase(IEnumerable<ICoroutine> coroutine)
        {
            if (Phasing != null)
                Phasing.Dispose();
            if (coroutine == null)
                Phasing = null;
            else
                Phasing = new COROUTINE(coroutine);
        }
        internal void OnPhaseLoading()
        {
            Phase = EPhase.Loading;
            SetPhase(Loading());
            if (PhaseLoading != null)
                PhaseLoading(this, Content);
        }
        internal void OnLoadCompleted()
        {
            if (loadings.Count == 0)
                if (LoadCompleted != null)
                    LoadCompleted(this, Content);
        }
        internal void OnPhasePreparing()
        {
            OnLoadCompleted();
            Phase = EPhase.Preparing;
            switch (ShowPosition)
            {
                case EShowPosition.ParentCenter:
                    Pivot = EPivot.MiddleCenter;
                    if (Parent != null)
                        Location = Parent.Size * 0.5f;
                    else
                    {
                        //goto case EShowPosition.GraphicsCenter;
                        Pivot = EPivot.MiddleCenter;
                        Location = Entry.GRAPHICS.GraphicsSize * 0.5f;
                    }
                    break;

                case EShowPosition.GraphicsCenter:
                    Pivot = EPivot.MiddleCenter;
                    Location = Entry.GRAPHICS.GraphicsSize * 0.5f;
                    break;
            }
            SetPhase(Preparing());
            if (PhasePreparing != null)
                PhasePreparing(this);
        }
        internal void OnPhasePrepared()
        {
            Phase = EPhase.Prepared;
            if (PhasePrepared != null)
                PhasePrepared(this);
        }
        /// <summary>
        /// Scene进入到Entry
        /// </summary>
        /// <param name="previous">切换菜单则是前一个主菜单，二级菜单则为当前主菜单</param>
        internal void OnPhaseShowing()
        {
            Phase = EPhase.Showing;
            SetPhase(Showing());
            if (PhaseShowing != null)
                PhaseShowing(this);
        }
        internal void OnPhaseShown()
        {
            Phase = EPhase.Running;
            SetPhase(Running());
            if (PhaseShown != null)
                PhaseShown(this);
        }
        internal void OnPhaseEnding()
        {
            Phase = EPhase.Ending;
            SetPhase(Ending());
            if (PhaseEnding != null)
                PhaseEnding(this);
        }
        /// <summary>
        /// Scene从Entry移除
        /// </summary>
        /// <param name="next">换菜单则是即将切换到的菜单，否则为null</param>
        internal void OnPhaseEnded()
        {
            Phase = EPhase.None;
            if (PhaseEnded != null)
                PhaseEnded(this);
            Entry = null;
        }
        
        public void ChangeFlowLayout(bool useFlowLayout)
        {
            if (UseFlowLayout == useFlowLayout) return;
            this.UseFlowLayout = useFlowLayout;
            if (useFlowLayout)
            {
                // 原本的xy坐标自动转换成相应的magin值
                ForParentPriority(this, e => e.ChildCount < 2,
                    e =>
                    {
                        // 按Bottom排序
                        Utility.SortOrderAsc(e.Childs, s => (int)s.Clip.Bottom);
                    });
                UIElement pre = null;
                float y = 0;
                ForRootToLeaf(this, e =>
                    {
                        if (pre != null)
                        {
                            if (e.X <= pre.X || pre.Flow.Line)
                            {
                                pre.Flow.Line = true;
                                e.Flow.MaginLeft = e.X;
                                e.Flow.MaginTop = e.Y - pre.Flow.MaginTop - pre.Height - y;
                                y += pre.Flow.MaginTop + pre.Height;
                            }
                            else
                            {
                                e.Flow.MaginLeft = (e.X - pre.X - pre.Width);
                                e.Flow.MaginTop = (e.Y - pre.Y) + pre.Flow.MaginTop;
                            }
                        }
                        else
                        {
                            e.Flow.MaginLeft = e.X;
                            e.Flow.MaginTop = e.Y;
                        }
                        pre = e;
                    },
                    e =>
                    {
                        pre = null;
                        y = 0;
                    });
            }
            else
            {
                // 取消所有已经计算好的Flow.Y和Flow.Bottom
                ForRootToLeaf(this, e =>
                {
                    e.Flow.Y = 0;
                    e.Flow.Bottom = 0;
                });
            }
            NeedUpdateLocalToWorld = true;
        }
        internal void FlowLayout()
        {
            if (!UseFlowLayout || Parent != null || Entry == null)
                return;

            float x = 0;
            float preY = 0;
            float breaklineWidth = 0;
            UIElement.ForRootToLeaf(this,
                e =>
                {
                    x += e.Flow.MaginLeft;
                    if (breaklineWidth > 0)
                    {
                        // 自动换行
                        if (x + e.Width + e.Flow.MaginRight > breaklineWidth)
                        {
                            x = e.Flow.MaginLeft;
                            preY = e.Parent.Flow.Bottom;
                        }
                    }
                    float y = preY + e.Flow.MaginTop;
                    e.X = x;
                    e.Y = y;
                    x += e.Width + e.Flow.MaginRight;
                    y += e.Height + e.Flow.MaginBottom;
                    if (y >= e.Parent.Flow.Bottom)
                        e.Parent.Flow.Bottom = y;
                    // 换行
                    if (e.Flow.Line)
                    {
                        x = 0;
                        preY = e.Parent.Flow.Bottom;
                    }
                },
                e =>
                {
                    x = 0;
                    e.Flow.Bottom = 0;
                    if (e.Parent != null)
                    {
                        e.Flow.Y = e.Parent.Flow.Bottom;
                        preY = e.Flow.Y;
                    }
                    // 父容器是固定宽度则自动换行
                    if (e.IsAutoWidth) breaklineWidth = 0;
                    else breaklineWidth = e.Width;
                });
        }
        /// <summary>场景从舞台移除之前的结束阶段：执行更新，绘制</summary>
        protected internal virtual IEnumerable<ICoroutine> Ending()
        {
            return null;
        }
        /// <summary>场景进入舞台前的加载阶段：不执行任何流程</summary>
        protected internal virtual IEnumerable<ICoroutine> Loading()
        {
            return null;
        }
        /// <summary>场景进入舞台前的准备阶段：执行渲染</summary>
        protected internal virtual IEnumerable<ICoroutine> Preparing()
        {
            return null;
        }
        /// <summary>场景进入舞台前的阶段：执行更新，绘制</summary>
        protected internal virtual IEnumerable<ICoroutine> Showing()
        {
            return null;
        }
        /// <summary>场景正在运行</summary>
        protected internal virtual IEnumerable<ICoroutine> Running()
        {
            return null;
        }
        /// <summary><para>异步加载协程，在Load中调用</para>
        /// <para>1. LoadAsync 完全不阻断协程</para>
        /// <para>2. yield return LoadAsync 阻断协程直到异步加载完成，可以自定义ICoroutine来实现加载条</para>
        /// </summary>
        /// <param name="async">异步加载状态</param>
        /// <returns>阻断协程</returns>
        protected virtual ICoroutine LoadAsync(AsyncLoadContent async)
        {
            if (!async.IsEnd)
            {
                loadings.Add(async);
                return async;
            }
            return null;
        }
        internal void Show(Entry entry)
        {
            this.Entry = entry;

            SetPhase(null);

            if (IsDisposed)
            {
                if (ContentType == EContent.Inherit)
                {
                    // inherit from parent scene
                    if (Parent != null && Parent.Scene != null)
                    {
                        Content = Parent.Scene.Content;
                    }

                    // inherit from current main scene
                    if (Content == null && Entry.Scene != null)
                    {
                        Content = Entry.Scene.Content;
                    }
                }
                else if (ContentType == EContent.System)
                {
                    if (entry.ContentManager != null)
                    {
                        Content = entry.ContentManager;
                    }
                }

                if (Content == null)
                {
                    Content = entry.NewContentManager();
                }
            }
        }
        /// <summary>从舞台中移除场景</summary>
        public void Close(bool immediately)
        {
            Close(State, immediately);
        }
        /// <summary>从舞台中移除场景</summary>
        /// <param name="state">关闭场景的状态，是否要释放资源等</param>
        /// <param name="immediately">true: 立即关闭，直接从舞台中移除，不仅过结束阶段</param>
        public void Close(EState state, bool immediately)
        {
            if (Entry == null)
                return;

            if (immediately)
                Entry.CloseImmediately(this, state);
            else
                Entry.Close(this, state);
        }
        /// <summary>场景在其它场景里时，被Remove或Clear时需要关闭此场景</summary>
        //protected override void OnRemovedBy(UIElement parent)
        //{
        //    base.OnRemovedBy(parent);
        //    Close(true);
        //}
        /// <summary>层级显示到最前面</summary>
        public override void ToFront()
        {
            if (Entry == null)
                base.ToFront();
            else
                Entry.ToFront(this);
        }
        /// <summary>层级显示到最后面</summary>
        public override void ToBack()
        {
            if (Entry == null)
                base.ToBack();
            else
                Entry.ToBack(this);
        }
        protected override void InternalUpdate(Entry e)
        {
            if (loadings.Count > 0)
            {
                loadings = loadings.Where(l => !l.IsEnd).ToList();
                OnLoadCompleted();
            }
            base.InternalUpdate(e);
        }
        public void DoKeyboard(UIElement sender, Entry e)
        {
            if (Parent == null && IsInStage && Entry.Scene == this && e.INPUT.Keyboard.IsClick(FocusNextKey))
            {
                UIElement next = FocusedElement;
                if (next == null)
                    // 第一个可以设置焦点的控件
                    next = NextFocusedElement;
                else
                    // 当前焦点的下一个焦点控件
                    next = next.NextFocusedElement;

                if (next != null)
                    next.SetFocus(true);
                else if (FocusedElement != null)
                    // 最后的焦点控件后设置为无焦点
                    FocusedElement.SetFocus(false);
            }
        }
        protected override void DrawEnd(GRAPHICS spriteBatch, ref MATRIX2x3 transform, ref RECT view, SHADER shader)
        {
            while (TopMost.Count > 0)
                TopMost.Dequeue().Draw(spriteBatch, Entry.Instance);

            base.DrawEnd(spriteBatch, ref transform, ref view, shader);
        }
        public override void Dispose()
        {
            foreach (var loading in loadings)
                if (!loading.IsEnd)
                    loading.Cancel();
            loadings.Clear();
            base.Dispose();
            if (Content != null && Content != Entry.Instance.ContentManager)
            {
                Content.Dispose();
                Content = null;
            }
            State = EState.Dispose;
            SetPhase(null);
            TopMost.Clear();
        }
    }

    /// <summary>UI文字显示</summary>
    public class UIText
    {
        /// <summary>显示的文字内容</summary>
        public string Text = "";
        private FONT font = FONT.Default;
        /// <summary>文字显示的颜色</summary>
        public COLOR FontColor = COLOR.Default;
        /// <summary>文字对齐方式</summary>
        public EPivot TextAlignment;
        /// <summary>文字阴影</summary>
        public TextShader TextShader;
        /// <summary>描边</summary>
        public ShaderStroke Stroke;
        /// <summary>相对于父容器的间隔</summary>
        public VECTOR2 Padding;
        /// <summary>文字缩放，缩放过大可能会使文字模糊</summary>
        public float Scale = 1f;

        /// <summary>字体</summary>
        public FONT Font
        {
            get { return font; }
            set
            {
                if (font == null || value == null)
                    font = value;
                else
                {
                    float fontSize = font.FontSize;
                    font = value;
                    font.FontSize = fontSize;
                }
            }
        }
        /// <summary>修改字体尺寸大小</summary>
        public float FontSize
        {
            get { return font == null ? 0 : font.FontSize; }
            set { if (font != null) font.FontSize = value; }
        }

        public void GetPaddingClip(ref RECT rect)
        {
            int x = UIElement.PivotX(TextAlignment);
            int y = UIElement.PivotY(TextAlignment);
            rect.X += Padding.X * 0.5f;
            rect.Width -= Padding.X;
            rect.Y += Padding.Y * 0.5f;
            rect.Height -= Padding.Y;
        }
        public void GetAlignmentClip(ref RECT rect, out float offsetX, out float offsetY)
        {
            int x = UIElement.PivotX(TextAlignment);
            int y = UIElement.PivotY(TextAlignment);
            VECTOR2 size = font.MeasureString(Text);
            offsetX = (rect.Width - size.X) * 0.5f * x;
            offsetY = (rect.Height - size.Y) * 0.5f * y;
            rect.X += offsetX;
            rect.Y += offsetY;
            if (offsetX < 0)
                rect.Width += -offsetX * 2;
            if (offsetY < 0)
                rect.Height += -offsetY * 2;
        }
        public RECT GetTextClip(RECT rect)
        {
            int x = UIElement.PivotX(TextAlignment);
            int y = UIElement.PivotY(TextAlignment);
            rect.X += Padding.X * 0.5f;
            rect.Width -= Padding.X;
            rect.Y += Padding.Y * 0.5f;
            rect.Height -= Padding.Y;

            VECTOR2 size = font.MeasureString(Text) * Scale;
            float offsetX = (rect.Width - size.X) * 0.5f * x;
            float offsetY = (rect.Height - size.Y) * 0.5f * y;
            rect.X += offsetX;
            rect.Y += offsetY;
            if (offsetX < 0)
                rect.Width += -offsetX * 2;
            if (offsetY < 0)
                rect.Height += -offsetY * 2;
            return rect;
        }
        public void Draw(GRAPHICS spriteBatch, RECT rect)
        {
            if (font != null && !string.IsNullOrEmpty(Text))
            {
                VECTOR2 location = GetTextClip(rect).Location;
                if (TextShader != null && TextShader.HasOffset)
                    spriteBatch.BaseDrawFont(font, Text, location.X + TextShader.Offset.X, location.Y + TextShader.Offset.Y, TextShader.Color, Scale);
                if (Stroke != null)
                    spriteBatch.Begin(Stroke);
                spriteBatch.BaseDrawFont(font, Text, location.X, location.Y, FontColor, Scale);
                if (Stroke != null)
                    spriteBatch.End();
            }
        }
    }
}

#endif